${SRCDIR}/GameInitDispose.cpp
${SRCDIR}/GameTick.cpp
${SRCDIR}/Globals.cpp
+ ${SRCDIR}/Tutorial.cpp
)
${SRCDIR}/Utils/Input.hpp
${SRCDIR}/Utils/private.h
${SRCDIR}/Game.hpp
+ ${SRCDIR}/Tutorial.hpp
)
#include "Audio/openal_wrapper.hpp"
#include "Game.hpp"
#include "Utils/Folders.hpp"
+#include "Tutorial.hpp"
extern float multiplier;
extern float gravity;
extern float camerashake;
extern bool freeze;
extern int detail;
-extern int tutoriallevel;
extern int whichjointstartarray[26];
extern int whichjointendarray[26];
if (joints[i].label == groin && !joints[i].locked && joints[i].delay <= 0) {
joints[i].locked = 1;
joints[i].delay = 1;
- if (tutoriallevel != 1 || id == 0) {
+ if (!Tutorial::active || id == 0) {
emit_sound_at(landsound1, joints[i].position * (*scale) + *coords, 128.);
}
breaking = true;
if (joints[i].label == head && !joints[i].locked && joints[i].delay <= 0) {
joints[i].locked = 1;
joints[i].delay = 1;
- if (tutoriallevel != 1 || id == 0) {
+ if (!Tutorial::active || id == 0) {
emit_sound_at(landsound2, joints[i].position * (*scale) + *coords, 128.);
}
}
else
joints[i].velocity = 0;
- if (tutoriallevel != 1 || id == 0)
+ if (!Tutorial::active || id == 0)
if (findLengthfast(&bounceness) > 8000 && breaking) {
// FIXME: this crashes because k is not initialized!
// to reproduce, type 'wolfie' in console and play a while
if (joints[i].label == groin && !joints[i].locked && joints[i].delay <= 0) {
joints[i].locked = 1;
joints[i].delay = 1;
- if (tutoriallevel != 1 || id == 0) {
+ if (!Tutorial::active || id == 0) {
emit_sound_at(landsound1, joints[i].position * (*scale) + *coords, 128.);
}
breaking = true;
if (joints[i].label == head && !joints[i].locked && joints[i].delay <= 0) {
joints[i].locked = 1;
joints[i].delay = 1;
- if (tutoriallevel != 1 || id == 0) {
+ if (!Tutorial::active || id == 0) {
emit_sound_at(landsound2, joints[i].position * (*scale) + *coords, 128.);
}
}
bounceness = 0;
joints[i].velocity = joints[i].oldvelocity;
}
- if (tutoriallevel != 1 || id == 0)
+ if (!Tutorial::active || id == 0)
if (findLengthfast(&bounceness) > 4000 && breaking) {
Object::objects[k]->model.MakeDecal(breakdecal, DoRotation(temp - Object::objects[k]->position, 0, -Object::objects[k]->yaw, 0), .4, .5, Random() % 360);
Sprite::MakeSprite(cloudsprite, joints[i].position * (*scale) + *coords, joints[i].velocity * .06, 1, 1, 1, 4, .2);
drawmodel.Rotate(180, 0, 0);
drawmodel.Scale(.04, .04, .04);
drawmodel.FlipTexCoords();
- if ((tutoriallevel == 1) && (id != 0)) {
+ if ((Tutorial::active) && (id != 0)) {
drawmodel.UniformTexCoords();
drawmodel.ScaleTexCoords(0.1);
}
drawmodellow.Rotate(180, 0, 0);
drawmodellow.Scale(.04, .04, .04);
drawmodellow.FlipTexCoords();
- if (tutoriallevel == 1 && id != 0)
+ if (Tutorial::active && id != 0)
drawmodellow.UniformTexCoords();
- if (tutoriallevel == 1 && id != 0)
+ if (Tutorial::active && id != 0)
drawmodellow.ScaleTexCoords(0.1);
drawmodellow.CalculateNormals(0);
#include "Level/Dialog.hpp"
#include "Level/Hotspot.hpp"
#include "Utils/Folders.hpp"
+#include "Tutorial.hpp"
const char *cmd_names[cmd_count] = {
#define DECLARE_COMMAND(cmd) #cmd,
extern float fadestart;
extern float slomospeed;
extern float slomofreq;
-extern int tutoriallevel;
extern int hostile;
extern int maptype;
extern int slomo;
void ch_tutorial(const char *args)
{
- tutoriallevel = atoi(args);
+ Tutorial::active = atoi(args);
}
void ch_hostile(const char *args)
#include "Game.hpp"
#include "Objects/Object.hpp"
#include "Utils/Folders.hpp"
+#include "Tutorial.hpp"
extern XYZ viewer;
extern float viewdistance;
extern float targetblurness;
extern bool visibleloading;
extern bool skyboxtexture;
-extern int tutoriallevel;
//Functions
lightloc.x = 0;
lightloc.z = 0;
}
- if (skyboxtexture && tutoriallevel) {
+ if (skyboxtexture && Tutorial::active) {
lightloc.x *= .4;
lightloc.z *= .4;
}
void playdialoguescenesound();
int findClosestPlayer();
void Loadlevel(int which);
-void Loadlevel(const std::string& name);
+void Loadlevel(const std::string& name, bool tutorial = false);
void Tick();
void TickOnce();
void TickOnceAfter();
#include "Level/Hotspot.hpp"
#include "Menu/Menu.hpp"
#include "Utils/Input.hpp"
+#include "Tutorial.hpp"
extern XYZ viewer;
extern int environment;
extern bool decals;
extern float texdetail;
extern bool musictoggle;
-extern int tutoriallevel;
extern float smoketex;
-extern float tutorialstagetime;
-extern float tutorialmaxtime;
-extern int tutorialstage;
extern bool againbonus;
extern float damagedealt;
extern bool invertmouse;
point = DoRotation(Person::players[k]->skeleton.joints[i].position, 0, Person::players[k]->yaw, 0) * Person::players[k]->scale + Person::players[k]->coords;
size = .4f;
opacity = .4 - Person::players[k]->skeleton.joints[i].position.y * Person::players[k]->scale / 5 - (Person::players[k]->coords.y - terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z)) / 10;
- if (k != 0 && tutoriallevel == 1) {
+ if (k != 0 && Tutorial::active) {
opacity = .2 + .2 * sin(smoketex * 6 + i) - Person::players[k]->skeleton.joints[i].position.y * Person::players[k]->scale / 5 - (Person::players[k]->coords.y - terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z)) / 10;
}
terrain.MakeDecal(shadowdecal, point, size, opacity, rotation);
point = DoRotation(DoRotation(Person::players[k]->skeleton.joints[i].position, 0, Person::players[k]->yaw, 0) * Person::players[k]->scale + Person::players[k]->coords - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
size = .4f;
opacity = .4f;
- if (k != 0 && tutoriallevel == 1) {
+ if (k != 0 && Tutorial::active) {
opacity = .2 + .2 * sin(smoketex * 6 + i);
}
Object::objects[j]->model.MakeDecal(shadowdecal, &point, &size, &opacity, &rotation);
point = DoRotation(Person::players[k]->skeleton.joints[i].position, 0, Person::players[k]->yaw, 0) * Person::players[k]->scale + Person::players[k]->coords;
size = .4f;
opacity = .4 - Person::players[k]->skeleton.joints[i].position.y * Person::players[k]->scale / 5 - (Person::players[k]->coords.y - terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z)) / 5;
- if (k != 0 && tutoriallevel == 1) {
+ if (k != 0 && Tutorial::active) {
opacity = .2 + .2 * sin(smoketex * 6 + i) - Person::players[k]->skeleton.joints[i].position.y * Person::players[k]->scale / 5 - (Person::players[k]->coords.y - terrain.getHeight(Person::players[k]->coords.x, Person::players[k]->coords.z)) / 10;
}
terrain.MakeDecal(shadowdecal, point, size, opacity * .7, rotation);
point = DoRotation(DoRotation(Person::players[k]->skeleton.joints[i].position, 0, Person::players[k]->yaw, 0) * Person::players[k]->scale + Person::players[k]->coords - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
size = .4f;
opacity = .4f;
- if (k != 0 && tutoriallevel == 1) {
+ if (k != 0 && Tutorial::active) {
opacity = .2 + .2 * sin(smoketex * 6 + i);
}
Object::objects[j]->model.MakeDecal(shadowdecal, &point, &size, &opacity, &rotation);
glCullFace(GL_FRONT);
glDepthMask(1);
for (unsigned k = 0; k < Person::players.size(); k++) {
- if (k == 0 || tutoriallevel != 1) {
+ if (k == 0 || !Tutorial::active) {
glEnable(GL_BLEND);
glEnable(GL_LIGHTING);
terrainlight = terrain.getLighting(Person::players[k]->coords.x, Person::players[k]->coords.z);
glCullFace(GL_FRONT);
glDepthMask(1);
for (unsigned k = 0; k < Person::players.size(); k++) {
- if (!(k == 0 || tutoriallevel != 1)) {
+ if (!(k == 0 || !Tutorial::active)) {
glEnable(GL_BLEND);
glEnable(GL_LIGHTING);
terrainlight = terrain.getLighting(Person::players[k]->coords.x, Person::players[k]->coords.z);
glEnable(GL_TEXTURE_2D);
glColor4f(.5, .5, .5, 1);
if (!console) {
- if (!tutoriallevel)
+ if (!Tutorial::active)
if (bonus > 0 && bonustime < 1 && !winfreeze && !Dialog::inDialog()) {
const char *bonus_name;
if (bonus < bonus_count)
glColor4f(.5, .5, .5, 1);
}
- if (tutoriallevel == 1) {
- tutorialopac = tutorialmaxtime - tutorialstagetime;
- if (tutorialopac > 1)
- tutorialopac = 1;
- if (tutorialopac < 0)
- tutorialopac = 0;
-
- string = " ";
- string2 = " ";
- string3 = " ";
- if (tutorialstage == 0) {
- string = " ";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 1) {
- string = "Welcome to the Lugaru training level!";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 2) {
- string = "BASIC MOVEMENT:";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 3) {
- string = "You can move the mouse to rotate the camera.";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 4) {
- string = std::string("Try using the ") +
- Input::keyToChar(forwardkey) + ", " +
- Input::keyToChar(leftkey) + ", " +
- Input::keyToChar(backkey) + " and " +
- Input::keyToChar(rightkey) + " keys to move around.";
- string2 = "All movement is relative to the camera.";
- string3 = " ";
- }
- if (tutorialstage == 5) {
- string = std::string("Please press ") + Input::keyToChar(jumpkey) + " to jump.";
- string2 = "You can hold it longer to jump higher.";
- string3 = " ";
- }
- if (tutorialstage == 6) {
- string = std::string("You can press ") + Input::keyToChar(crouchkey) + " to crouch.";
- string2 = "You can jump higher from a crouching position.";
- string3 = " ";
- }
- if (tutorialstage == 7) {
- string = std::string("While running, you can press ") + Input::keyToChar(crouchkey) + " to roll.";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 8) {
- string = "While crouching, you can sneak around silently";
- string2 = "using the movement keys.";
- string3 = " ";
- }
- if (tutorialstage == 9) {
- string = "Release the crouch key while sneaking and hold the movement keys";
- string2 = "to run animal-style.";
- string3 = " ";
- }
- if (tutorialstage == 10) {
- string = "ADVANCED MOVEMENT:";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 11) {
- string = std::string("When you jump at a wall, you can hold ") + Input::keyToChar(jumpkey) + " again";
- string2 = "during impact to perform a walljump.";
- string3 = "Be sure to use the movement keys to press against the wall";
- }
- if (tutorialstage == 12) {
- string = "While in the air, you can press crouch to flip.";
- string2 = "Walljumps and flips confuse enemies and give you more control.";
- string3 = " ";
- }
- if (tutorialstage == 13) {
- string = "BASIC COMBAT:";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 14) {
- string = "There is now an imaginary enemy";
- string2 = "in the middle of the training area.";
- string3 = " ";
- }
- if (tutorialstage == 15) {
- if (attackkey == MOUSEBUTTON1) {
- string = "Click to attack when you are near an enemy.";
- } else {
- string = std::string("Press ") + Input::keyToChar(attackkey) + " to attack when you are near an enemy.";
- }
- string2 = "You can punch by standing still near an enemy and attacking.";
- string3 = " ";
- }
- if (tutorialstage == 16) {
- string = "If you are close, you will perform a weak punch.";
- string2 = "The weak punch is excellent for starting attack combinations.";
- string3 = " ";
- }
- if (tutorialstage == 17) {
- string = "Attacking while running results in a spin kick.";
- string2 = "This is one of your most powerful ground attacks.";
- string3 = " ";
- }
- if (tutorialstage == 18) {
- string = "Sweep the enemy's legs out by attacking while crouched.";
- string2 = "This is a very fast attack, and easy to follow up.";
- string3 = " ";
- }
- if (tutorialstage == 19) {
- string = "When an enemy is on the ground, you can deal some extra";
- string2 = "damage by running up and drop-kicking him.";
- string3 = "(Try knocking them down with a sweep first)";
- }
- if (tutorialstage == 20) {
- string = "Your most powerful individual attack is the rabbit kick.";
- if (attackkey == MOUSEBUTTON1) {
- string2 = "Run at the enemy while holding the mouse button, and press";
- } else {
- string2 = std::string("Run at the enemy while holding ") + Input::keyToChar(attackkey) + ", and press";
- }
- string3 = std::string("the jump key (") + Input::keyToChar(jumpkey) + ") to attack.";
- }
- if (tutorialstage == 21) {
- string = "This attack is devastating if timed correctly.";
- string2 = "Even if timed incorrectly, it will knock the enemy over.";
- if (againbonus)
- string3 = "Try rabbit-kicking the imaginary enemy again.";
- else
- string3 = "Try rabbit-kicking the imaginary enemy.";
- }
- if (tutorialstage == 22) {
- string = "If you sneak behind an enemy unnoticed, you can kill";
- string2 = "him instantly. Move close behind this enemy";
- string3 = "and attack.";
- }
- if (tutorialstage == 23) {
- string = "Another important attack is the wall kick. When an enemy";
- string2 = "is near a wall, perform a walljump nearby and hold";
- string3 = "the attack key during impact with the wall.";
- }
- if (tutorialstage == 24) {
- string = "You can tackle enemies by running at them animal-style";
- if (attackkey == MOUSEBUTTON1) {
- string2 = std::string("and pressing jump (") + Input::keyToChar(jumpkey) + ") or attack(mouse button).";
- } else {
- string2 = std::string("and pressing jump (") + Input::keyToChar(jumpkey) + ") or attack(" + Input::keyToChar(attackkey) + ").";
- }
- string3 = "This is especially useful when they are running away.";
- }
- if (tutorialstage == 25) {
- string = "Dodge by pressing back and attack. Dodging is essential";
- string2 = "against enemies with swords or other long weapons.";
- string3 = " ";
- }
- if (tutorialstage == 26) {
- string = "REVERSALS AND COUNTER-REVERSALS";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 27) {
- string = "The enemy can now reverse your attacks.";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 28) {
- string = "If you attack, you will notice that the enemy now sometimes";
- string2 = "catches your attack and uses it against you. Hold";
- string3 = std::string("crouch (") + Input::keyToChar(crouchkey) + ") after attacking to escape from reversals.";
- }
- if (tutorialstage == 29) {
- string = "Try escaping from two more reversals in a row.";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 30) {
- string = "Good!";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 31) {
- string = std::string("To reverse an attack, you must tap crouch (") + Input::keyToChar(crouchkey) + ") during the";
- string2 = "enemy's attack. You must also be close to the enemy;";
- string3 = "this is especially important against armed opponents.";
- }
- if (tutorialstage == 32) {
- string = "The enemy can attack in " + to_string(int(tutorialmaxtime - tutorialstagetime)) + " seconds.";
- string2 = "This imaginary opponents attacks will be highlighted";
- string3 = "to make this easier.";
- }
- if (tutorialstage == 33) {
- string = "Reverse three enemy attacks!";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 34) {
- string = "Reverse two more enemy attacks!";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 35) {
- string = "Reverse one more enemy attack!";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 36) {
- string = "Excellent!";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 37) {
- string = "Now spar with the enemy for " + to_string(int(tutorialmaxtime - tutorialstagetime)) + " more seconds.";
- string2 = "Damage dealt: " + to_string(int(damagedealt));
- string3 = "Damage taken: " + to_string(int(damagetaken));
- }
- if (tutorialstage == 38) {
- string = "WEAPONS:";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 39) {
- string = "There is now an imaginary knife";
- string2 = "in the center of the training area.";
- string3 = " ";
- }
- if (tutorialstage == 40) {
- string = "Stand, roll or handspring over the knife";
- string2 = std::string("while pressing ") + Input::keyToChar(throwkey) + " to pick it up.";
- string3 = "You can crouch and press the same key to drop it again.";
- }
- if (tutorialstage == 41) {
- string = std::string("You can equip and unequip weapons using the ") + Input::keyToChar(drawkey) + " key.";
- string2 = "Sometimes it is best to keep them unequipped to";
- string3 = "prevent enemies from taking them. ";
- }
- if (tutorialstage == 42) {
- string = "The knife is the smallest weapon and the least encumbering.";
- string2 = "You can equip or unequip it while standing, crouching,";
- string3 = "running or flipping.";
- }
- if (tutorialstage == 43) {
- string = "You perform weapon attacks the same way as unarmed attacks,";
- string2 = "but sharp weapons cause permanent damage, instead of the";
- string3 = "temporary trauma from blunt weapons, fists and feet.";
- }
- if (tutorialstage == 44) {
- string = "The enemy now has your knife!";
- string2 = "Please reverse two of his knife attacks.";
- string3 = " ";
- }
- if (tutorialstage == 45) {
- string = "Please reverse one more of his knife attacks.";
- string2 = " ";
- string3 = " ";
- }
- if (tutorialstage == 46) {
- string = "Now he has a sword!";
- string2 = "The sword has longer reach than your arms, so you";
- string3 = "must move close to reverse the sword slash.";
- }
- if (tutorialstage == 47) {
- string = "Long weapons like the sword and staff are also useful for defense;";
- string2 = "you can parry enemy weapon attacks by pressing the attack key";
- string3 = "at the right time. Please try parrying the enemy's attacks!";
- }
- if (tutorialstage == 48) {
- string = "The staff is like the sword, but has two main attacks.";
- string2 = "The standing smash is fast and effective, and the running";
- string3 = "spin smash is slower and more powerful.";
- }
- if (tutorialstage == 49) {
- string = std::string("When facing an enemy, you can throw the knife with ") + Input::keyToChar(throwkey) + ".";
- string2 = "It is possible to throw the knife while flipping,";
- string3 = "but it is very inaccurate.";
- }
- if (tutorialstage == 50) {
- string = "You now know everything you can learn from training.";
- string2 = "Everything else you must learn from experience!";
- string3 = " ";
- }
- if (tutorialstage == 51) {
- string = "Walk out of the training area to return to the main menu.";
- string2 = " ";
- string3 = " ";
- }
-
- text->glPrintOutlined(1, 1, 1, tutorialopac, screenwidth / 2 - 7.6 * string.size()*screenwidth / 1024, screenheight / 16 + screenheight * 4 / 5, string, 1, 1.5 * screenwidth / 1024, screenwidth, screenheight);
- text->glPrintOutlined(1, 1, 1, tutorialopac, screenwidth / 2 - 7.6 * string2.size()*screenwidth / 1024, screenheight / 16 + screenheight * 4 / 5 - 20 * screenwidth / 1024, string2, 1, 1.5 * screenwidth / 1024, screenwidth, screenheight);
- text->glPrintOutlined(1, 1, 1, tutorialopac, screenwidth / 2 - 7.6 * string3.size()*screenwidth / 1024, screenheight / 16 + screenheight * 4 / 5 - 40 * screenwidth / 1024, string3, 1, 1.5 * screenwidth / 1024, screenwidth, screenheight);
-
- string = "Press 'tab' to skip to the next item.";
- string2 = "Press escape at any time to";
- string3 = "pause or exit the tutorial.";
-
- text->glPrintOutlined(0.5, 0.5, 0.5, 1, screenwidth / 2 - 7.6 * string.size()*screenwidth / 1024 * .8, 0 + screenheight * 1 / 10, string, 1, 1.5 * screenwidth / 1024 * .8, screenwidth, screenheight);
- text->glPrintOutlined(0.5, 0.5, 0.5, 1, screenwidth / 2 - 7.6 * string2.size()*screenwidth / 1024 * .8, 0 + screenheight * 1 / 10 - 20 * .8 * screenwidth / 1024, string2, 1, 1.5 * screenwidth / 1024 * .8, screenwidth, screenheight);
- text->glPrintOutlined(0.5, 0.5, 0.5, 1, screenwidth / 2 - 7.6 * string3.size()*screenwidth / 1024 * .8, 0 + screenheight * 1 / 10 - 40 * .8 * screenwidth / 1024, string3, 1, 1.5 * screenwidth / 1024 * .8, screenwidth, screenheight);
+ if (Tutorial::active) {
+ Tutorial::DrawText();
}
//Hot spots
- if (Hotspot::hotspots.size() && (bonustime >= 1 || bonus <= 0 || bonustime < 0) && !tutoriallevel) {
+ if (Hotspot::hotspots.size() && (bonustime >= 1 || bonus <= 0 || bonustime < 0) && !Tutorial::active) {
float closestdist = -1;
float distance = 0;
int closest = Hotspot::current;
Hotspot::current = closest;
if (Hotspot::hotspots[closest].type <= 10) {
if (distsq(&Person::players[0]->coords, &Hotspot::hotspots[closest].position) < Hotspot::hotspots[closest].size)
- tutorialstagetime = 0;
- tutorialmaxtime = 1;
- tutorialopac = tutorialmaxtime - tutorialstagetime;
+ Tutorial::stagetime = 0;
+ Tutorial::maxtime = 1;
+ tutorialopac = Tutorial::maxtime - Tutorial::stagetime;
if (tutorialopac > 1)
tutorialopac = 1;
if (tutorialopac < 0)
}
}
- if (!tutoriallevel && !winfreeze && !Dialog::inDialog() && !mainmenu) {
+ if (!Tutorial::active && !winfreeze && !Dialog::inDialog() && !mainmenu) {
if (campaign) {
if (scoreadded) {
string = "Score: " + to_string(int(Account::active().getCampaignScore()));
#include "User/Settings.hpp"
#include "Utils/Folders.hpp"
#include "Utils/Input.hpp"
+#include "Tutorial.hpp"
#if PLATFORM_UNIX
#include <sys/stat.h>
extern float fadestart;
extern float slomospeed;
extern float slomofreq;
-extern int tutoriallevel;
extern float smoketex;
-extern float tutorialstagetime;
-extern int tutorialstage;
-extern float tutorialmaxtime;
-extern float tutorialsuccess;
extern bool againbonus;
extern bool reversaltrain;
extern bool canattack;
whichlevel = which;
if (which == -1) {
- tutoriallevel = -1;
- Loadlevel("tutorial");
+ Loadlevel("tutorial", true);
} else if (which >= 0 && which <= 15) {
char buf[32];
snprintf(buf, 32, "map%d", which + 1); // challenges
Loadlevel("mapsave");
}
-void Game::Loadlevel(const std::string& name)
+void Game::Loadlevel(const std::string& name, bool tutorial)
{
int indemo; // FIXME this should be removed
int templength;
numenvsounds = 0;
- if (tutoriallevel != -1)
- tutoriallevel = 0;
- else
- tutoriallevel = 1;
+ Tutorial::active = tutorial;
- if (tutoriallevel == 1)
- tutorialstage = 0;
- if (tutorialstage == 0) {
- tutorialstagetime = 0;
- tutorialmaxtime = 1;
+ if (Tutorial::active) {
+ Tutorial::stage = 0;
+ }
+ if (Tutorial::stage == 0) {
+ Tutorial::stagetime = 0;
+ Tutorial::maxtime = 1;
}
pause_sound(whooshsound);
pause_sound(stream_firesound);
visibleloading = 0;
}
-void doTutorial()
-{
- if (tutorialstagetime > tutorialmaxtime) {
- tutorialstage++;
- tutorialsuccess = 0;
- if (tutorialstage <= 1) {
- canattack = 0;
- cananger = 0;
- reversaltrain = 0;
- }
- switch (tutorialstage) {
- case 1:
- tutorialmaxtime = 5;
- break;
- case 2:
- tutorialmaxtime = 2;
- break;
- case 3:
- tutorialmaxtime = 600;
- break;
- case 4:
- tutorialmaxtime = 1000;
- break;
- case 5:
- tutorialmaxtime = 600;
- break;
- case 6:
- tutorialmaxtime = 600;
- break;
- case 7:
- tutorialmaxtime = 600;
- break;
- case 8:
- tutorialmaxtime = 600;
- break;
- case 9:
- tutorialmaxtime = 600;
- break;
- case 10:
- tutorialmaxtime = 2;
- break;
- case 11:
- tutorialmaxtime = 1000;
- break;
- case 12:
- tutorialmaxtime = 1000;
- break;
- case 13:
- tutorialmaxtime = 2;
- break;
- case 14: {
- tutorialmaxtime = 3;
-
- XYZ temp, temp2;
-
- temp.x = 1011;
- temp.y = 84;
- temp.z = 491;
- temp2.x = 1025;
- temp2.y = 75;
- temp2.z = 447;
-
- Person::players[1]->coords = (temp + temp2) / 2;
-
- emit_sound_at(fireendsound, Person::players[1]->coords);
-
- for (unsigned i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
- if (Random() % 2 == 0) {
- if (!Person::players[1]->skeleton.free)
- temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
- if (Person::players[1]->skeleton.free)
- temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
- if (!Person::players[1]->skeleton.free)
- temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
- if (Person::players[1]->skeleton.free)
- temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
- Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
- }
- }
- }
- break;
- case 15:
- tutorialmaxtime = 500;
- break;
- case 16:
- tutorialmaxtime = 500;
- break;
- case 17:
- tutorialmaxtime = 500;
- break;
- case 18:
- tutorialmaxtime = 500;
- break;
- case 19:
- tutorialstage = 20;
- break;
- case 20:
- tutorialmaxtime = 500;
- break;
- case 21:
- tutorialmaxtime = 500;
- if (bonus == cannon) {
- bonus = Slicebonus;
- againbonus = 1;
- } else
- againbonus = 0;
- break;
- case 22:
- tutorialmaxtime = 500;
- break;
- case 23:
- tutorialmaxtime = 500;
- break;
- case 24:
- tutorialmaxtime = 500;
- break;
- case 25:
- tutorialmaxtime = 500;
- break;
- case 26:
- tutorialmaxtime = 2;
- break;
- case 27:
- tutorialmaxtime = 4;
- reversaltrain = 1;
- cananger = 1;
- Person::players[1]->aitype = attacktypecutoff;
- break;
- case 28:
- tutorialmaxtime = 400;
- break;
- case 29:
- tutorialmaxtime = 400;
- Person::players[0]->escapednum = 0;
- break;
- case 30:
- tutorialmaxtime = 4;
- reversaltrain = 0;
- cananger = 0;
- Person::players[1]->aitype = passivetype;
- break;
- case 31:
- tutorialmaxtime = 13;
- break;
- case 32:
- tutorialmaxtime = 8;
- break;
- case 33:
- tutorialmaxtime = 400;
- cananger = 1;
- canattack = 1;
- Person::players[1]->aitype = attacktypecutoff;
- break;
- case 34:
- tutorialmaxtime = 400;
- break;
- case 35:
- tutorialmaxtime = 400;
- break;
- case 36:
- tutorialmaxtime = 2;
- reversaltrain = 0;
- cananger = 0;
- Person::players[1]->aitype = passivetype;
- break;
- case 37:
- damagedealt = 0;
- damagetaken = 0;
- tutorialmaxtime = 50;
- cananger = 1;
- canattack = 1;
- Person::players[1]->aitype = attacktypecutoff;
- break;
- case 38:
- tutorialmaxtime = 4;
- canattack = 0;
- cananger = 0;
- Person::players[1]->aitype = passivetype;
- break;
- case 39: {
- XYZ temp, temp2;
-
- temp.x = 1011;
- temp.y = 84;
- temp.z = 491;
- temp2.x = 1025;
- temp2.y = 75;
- temp2.z = 447;
-
- Weapon w(knife, -1);
- w.position = (temp + temp2) / 2;
- w.tippoint = (temp + temp2) / 2;
-
- w.velocity = 0.1;
- w.tipvelocity = 0.1;
- w.missed = 1;
- w.hitsomething = 0;
- w.freetime = 0;
- w.firstfree = 1;
- w.physics = 1;
-
- weapons.push_back(w);
- }
- break;
- case 40:
- tutorialmaxtime = 300;
- break;
- case 41:
- tutorialmaxtime = 300;
- break;
- case 42:
- tutorialmaxtime = 8;
- break;
- case 43:
- tutorialmaxtime = 300;
- break;
- case 44:
- weapons[0].owner = 1;
- Person::players[0]->weaponactive = -1;
- Person::players[0]->num_weapons = 0;
- Person::players[1]->weaponactive = 0;
- Person::players[1]->num_weapons = 1;
- Person::players[1]->weaponids[0] = 0;
-
- cananger = 1;
- canattack = 1;
- Person::players[1]->aitype = attacktypecutoff;
-
- tutorialmaxtime = 300;
- break;
- case 45:
- weapons[0].owner = 1;
- Person::players[0]->weaponactive = -1;
- Person::players[0]->num_weapons = 0;
- Person::players[1]->weaponactive = 0;
- Person::players[1]->num_weapons = 1;
- Person::players[1]->weaponids[0] = 0;
-
- tutorialmaxtime = 300;
- break;
- case 46:
- weapons[0].owner = 1;
- Person::players[0]->weaponactive = -1;
- Person::players[0]->num_weapons = 0;
- Person::players[1]->weaponactive = 0;
- Person::players[1]->num_weapons = 1;
- Person::players[1]->weaponids[0] = 0;
-
- weapons[0].setType(sword);
-
- tutorialmaxtime = 300;
- break;
- case 47: {
- tutorialmaxtime = 10;
-
- XYZ temp, temp2;
-
- temp.x = 1011;
- temp.y = 84;
- temp.z = 491;
- temp2.x = 1025;
- temp2.y = 75;
- temp2.z = 447;
-
- Weapon w(sword, -1);
- w.position = (temp + temp2) / 2;
- w.tippoint = (temp + temp2) / 2;
-
- w.velocity = 0.1;
- w.tipvelocity = 0.1;
- w.missed = 1;
- w.hitsomething = 0;
- w.freetime = 0;
- w.firstfree = 1;
- w.physics = 1;
-
- weapons.push_back(w);
-
- weapons[0].owner = 1;
- weapons[1].owner = 0;
- Person::players[0]->weaponactive = 0;
- Person::players[0]->num_weapons = 1;
- Person::players[0]->weaponids[0] = 1;
- Person::players[1]->weaponactive = 0;
- Person::players[1]->num_weapons = 1;
- Person::players[1]->weaponids[0] = 0;
-
- }
- break;
- case 48:
- canattack = 0;
- cananger = 0;
- Person::players[1]->aitype = passivetype;
-
- tutorialmaxtime = 15;
-
- weapons[0].owner = 1;
- weapons[1].owner = 0;
- Person::players[0]->weaponactive = 0;
- Person::players[0]->num_weapons = 1;
- Person::players[0]->weaponids[0] = 1;
- Person::players[1]->weaponactive = 0;
- Person::players[1]->num_weapons = 1;
- Person::players[1]->weaponids[0] = 0;
-
- if (Person::players[0]->weaponactive != -1)
- weapons[Person::players[0]->weaponids[Person::players[0]->weaponactive]].setType(staff);
- else
- weapons[0].setType(staff);
- break;
- case 49:
- canattack = 0;
- cananger = 0;
- Person::players[1]->aitype = passivetype;
-
- tutorialmaxtime = 200;
-
- weapons[1].position = 1000;
- weapons[1].tippoint = 1000;
-
- weapons[0].setType(knife);
-
- weapons[0].owner = 0;
- Person::players[1]->weaponactive = -1;
- Person::players[1]->num_weapons = 0;
- Person::players[0]->weaponactive = 0;
- Person::players[0]->num_weapons = 1;
- Person::players[0]->weaponids[0] = 0;
-
- break;
- case 50: {
- tutorialmaxtime = 8;
-
- XYZ temp, temp2;
- emit_sound_at(fireendsound, Person::players[1]->coords);
-
- for (unsigned i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
- if (Random() % 2 == 0) {
- if (!Person::players[1]->skeleton.free)
- temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
- if (Person::players[1]->skeleton.free)
- temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
- if (!Person::players[1]->skeleton.free)
- temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
- if (Person::players[1]->skeleton.free)
- temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
- Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
- }
- }
-
- Person::players[1]->num_weapons = 0;
- Person::players[1]->weaponstuck = -1;
- Person::players[1]->weaponactive = -1;
-
- weapons.clear();
- }
- break;
- case 51:
- tutorialmaxtime = 80000;
- break;
- default:
- break;
- }
- if (tutorialstage <= 51)
- tutorialstagetime = 0;
- }
-
- //Tutorial success
- if (tutorialstagetime < tutorialmaxtime - 3) {
- switch (tutorialstage) {
- case 3:
- if (deltah || deltav)
- tutorialsuccess += multiplier;
- break;
- case 4:
- if (Person::players[0]->forwardkeydown || Person::players[0]->backkeydown || Person::players[0]->leftkeydown || Person::players[0]->rightkeydown)
- tutorialsuccess += multiplier;
- break;
- case 5:
- if (Person::players[0]->jumpkeydown)
- tutorialsuccess = 1;
- break;
- case 6:
- if (Person::players[0]->isCrouch())
- tutorialsuccess = 1;
- break;
- case 7:
- if (Person::players[0]->animTarget == rollanim)
- tutorialsuccess = 1;
- break;
- case 8:
- if (Person::players[0]->animTarget == sneakanim)
- tutorialsuccess += multiplier;
- break;
- case 9:
- if (Person::players[0]->animTarget == rabbitrunninganim || Person::players[0]->animTarget == wolfrunninganim)
- tutorialsuccess += multiplier;
- break;
- case 11:
- if (Person::players[0]->isWallJump())
- tutorialsuccess = 1;
- break;
- case 12:
- if (Person::players[0]->animTarget == flipanim)
- tutorialsuccess = 1;
- break;
- case 15:
- if (Person::players[0]->animTarget == upunchanim || Person::players[0]->animTarget == winduppunchanim)
- tutorialsuccess = 1;
- break;
- case 16:
- if (Person::players[0]->animTarget == winduppunchanim)
- tutorialsuccess = 1;
- break;
- case 17:
- if (Person::players[0]->animTarget == spinkickanim)
- tutorialsuccess = 1;
- break;
- case 18:
- if (Person::players[0]->animTarget == sweepanim)
- tutorialsuccess = 1;
- break;
- case 19:
- if (Person::players[0]->animTarget == dropkickanim)
- tutorialsuccess = 1;
- break;
- case 20:
- if (Person::players[0]->animTarget == rabbitkickanim)
- tutorialsuccess = 1;
- break;
- case 21:
- if (bonus == cannon)
- tutorialsuccess = 1;
- break;
- case 22:
- if (bonus == spinecrusher)
- tutorialsuccess = 1;
- break;
- case 23:
- if (Person::players[0]->animTarget == walljumprightkickanim || Person::players[0]->animTarget == walljumpleftkickanim)
- tutorialsuccess = 1;
- break;
- case 24:
- if (Person::players[0]->animTarget == rabbittacklinganim)
- tutorialsuccess = 1;
- break;
- case 25:
- if (Person::players[0]->animTarget == backhandspringanim)
- tutorialsuccess = 1;
- break;
- case 28:
- if (Animation::animations[Person::players[0]->animTarget].attack == reversed && Person::players[0]->feint)
- tutorialsuccess = 1;
- break;
- case 29:
- if (Person::players[0]->escapednum == 2) {
- tutorialsuccess = 1;
- reversaltrain = 0;
- cananger = 0;
- Person::players[1]->aitype = passivetype;
- }
- break;
- case 33:
- if (Animation::animations[Person::players[0]->animTarget].attack == reversal)
- tutorialsuccess = 1;
- break;
- case 34:
- if (Animation::animations[Person::players[0]->animTarget].attack == reversal)
- tutorialsuccess = 1;
- break;
- case 35:
- if (Animation::animations[Person::players[0]->animTarget].attack == reversal) {
- tutorialsuccess = 1;
- reversaltrain = 0;
- cananger = 0;
- Person::players[1]->aitype = passivetype;
- }
- break;
- case 40:
- if (Person::players[0]->num_weapons > 0)
- tutorialsuccess = 1;
- break;
- case 41:
- if (Person::players[0]->weaponactive == -1 && Person::players[0]->num_weapons > 0)
- tutorialsuccess = 1;
- break;
- case 43:
- if (Person::players[0]->animTarget == knifeslashstartanim)
- tutorialsuccess = 1;
- break;
- case 44:
- if (Animation::animations[Person::players[0]->animTarget].attack == reversal)
- tutorialsuccess = 1;
- break;
- case 45:
- if (Animation::animations[Person::players[0]->animTarget].attack == reversal)
- tutorialsuccess = 1;
- break;
- case 46:
- if (Animation::animations[Person::players[0]->animTarget].attack == reversal)
- tutorialsuccess = 1;
- break;
- case 49:
- if (Person::players[1]->weaponstuck != -1)
- tutorialsuccess = 1;
- break;
- default:
- break;
- }
- if (tutorialsuccess >= 1)
- tutorialstagetime = tutorialmaxtime - 3;
-
-
- if (tutorialstagetime == tutorialmaxtime - 3) {
- emit_sound_np(consolesuccesssound);
- }
-
- if (tutorialsuccess >= 1) {
- if (tutorialstage == 34 || tutorialstage == 35)
- tutorialstagetime = tutorialmaxtime - 1;
- }
- }
-
- if (tutorialstage < 14 || tutorialstage >= 50) {
- Person::players[1]->coords.y = 300;
- Person::players[1]->velocity = 0;
- }
-}
-
void doDevKeys()
{
float headprop, bodyprop, armprop, legprop;
}
if (attackweapon) {
//sweep
- if ((tutoriallevel != 1 || !attackweapon) &&
+ if ((!Tutorial::active || !attackweapon) &&
distance < 2.5 * sq(Person::players[k]->scale * 5) &&
randattack == 0 &&
Animation::animations[Person::players[i]->animTarget].height != lowheight)
randattack >= 3)
Person::players[k]->animTarget = staffspinhitanim;
//spinkick
- else if ((tutoriallevel != 1 || !attackweapon) &&
+ else if ((!Tutorial::active || !attackweapon) &&
distance < 2.5 * sq(Person::players[k]->scale * 5) &&
randattack == 1 &&
Animation::animations[Person::players[i]->animTarget].height != lowheight)
Person::players[k]->animTarget = wolfslapanim;
}
//sneak attacks
- if ((k == 0) && (tutoriallevel != 1 || tutorialstage == 22) &&
+ if ((k == 0) && (!Tutorial::active || Tutorial::stage == 22) &&
Person::players[i]->howactive < typedead1 &&
distance < 1.5 * sq(Person::players[k]->scale * 5) &&
!Person::players[i]->skeleton.free &&
distance < 1.5 * sq(Person::players[k]->scale * 5)))) {
Person::players[k]->victim = Person::players[i];
Person::players[k]->hasvictim = 1;
- if (attackweapon && tutoriallevel != 1) {
+ if (attackweapon && !Tutorial::active) {
//crouchstab
if (Person::players[k]->crouchkeydown && attackweapon == knife && distance < 1.5 * sq(Person::players[k]->scale * 5))
Person::players[k]->animTarget = crouchstabanim;
(k != 0 || Person::players[k]->skeleton.free) ||
(Animation::animations[Person::players[i]->animTarget].height == highheight &&
Animation::animations[Person::players[k]->animTarget].height == highheight)) {
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, Person::players[i]->coords);
}
if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
Person::players[i]->jumpkeydown = 1;
- if ((tutoriallevel != 1 || cananger) &&
+ if ((!Tutorial::active || cananger) &&
hostile &&
!Person::players[0]->dead &&
distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400 &&
//hearing sounds
if (!editorenabled) {
if (Person::players[i]->howactive <= typesleeping)
- if (numenvsounds > 0 && (tutoriallevel != 1 || cananger) && hostile)
+ if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile)
for (int j = 0; j < numenvsounds; j++) {
float vol = Person::players[i]->howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
if (vol > 0 && distsq(&Person::players[i]->coords, &envsound[j]) <
}
if (Person::players[i]->howactive < typesleeping &&
- ((tutoriallevel != 1 || cananger) && hostile) &&
+ ((!Tutorial::active || cananger) && hostile) &&
!Person::players[0]->dead &&
distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400 &&
Person::players[i]->occluded < 25) {
if ((Person::players[i]->collided > .8 && Person::players[i]->jumppower >= 5))
Person::players[i]->jumpkeydown = 1;
- if (numenvsounds > 0 && ((tutoriallevel != 1 || cananger) && hostile))
+ if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile))
for (int k = 0; k < numenvsounds; k++) {
if (distsq(&Person::players[i]->coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (Person::players[i]->creature == rabbittype) * 3)) {
Person::players[i]->aitype = attacktypecutoff;
Person::players[i]->losupdatedelay < 0 &&
!editorenabled &&
Person::players[i]->occluded < 2 &&
- ((tutoriallevel != 1 || cananger) && hostile)) {
+ ((!Tutorial::active || cananger) && hostile)) {
Person::players[i]->losupdatedelay = .2;
if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 4 && Animation::animations[Person::players[i]->animTarget].height != lowheight) {
Person::players[i]->aitype = attacktypecutoff;
Person::players[i]->lastseentime = 12;
- if (!Person::players[0]->dead && ((tutoriallevel != 1 || cananger) && hostile))
+ if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile))
if (Person::players[i]->ally < 0 || Person::players[i]->weaponactive != -1 || Person::players[i]->lastchecktime <= 0) {
Person::players[i]->aitype = attacktypecutoff;
Person::players[i]->lastseentime = 1;
for (unsigned j = 0; j < Person::players.size(); j++)
if (j != i && !Person::players[j]->skeleton.free &&
Person::players[j]->hasvictim &&
- (tutoriallevel == 1 && reversaltrain ||
+ (Tutorial::active && reversaltrain ||
Random() % 2 == 0 && difficulty == 2 ||
Random() % 4 == 0 && difficulty == 1 ||
Random() % 8 == 0 && difficulty == 0 ||
if (Person::players[i]->jumpkeydown)
Person::players[i]->attackkeydown = 0;
- if (tutoriallevel == 1)
+ if (Tutorial::active)
if (!canattack)
Person::players[i]->attackkeydown = 0;
}
- if (Input::isKeyPressed(SDL_SCANCODE_TAB) && tutoriallevel) {
- if (tutorialstage != 51)
- tutorialstagetime = tutorialmaxtime;
+ if (Input::isKeyPressed(SDL_SCANCODE_TAB) && Tutorial::active) {
+ if (Tutorial::stage != 51) {
+ Tutorial::stagetime = Tutorial::maxtime;
+ }
emit_sound_np(consolefailsound, 128.);
}
windvar += multiplier;
smoketex += multiplier;
- tutorialstagetime += multiplier;
+ Tutorial::stagetime += multiplier;
//hotspots
static float hotspotvisual[40];
}
//Tutorial
- if (tutoriallevel) {
- doTutorial();
+ if (Tutorial::active) {
+ Tutorial::Do(multiplier);
}
//bonuses
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
if (bonustime == 0 &&
bonus != solidhit &&
bonus != spinecrusher &&
bonusnum[bonus]++;
else
bonusnum[bonus] += 0.15;
- if (tutoriallevel)
+ if (Tutorial::active)
bonusvalue = 0;
bonusvalue /= bonusnum[bonus];
bonustotal += bonusvalue;
if (Person::players.size() > 1)
for (unsigned j = 0; j < Person::players.size(); j++) {
if (i != j)
- if (tutoriallevel != 1 || tutorialstage == 49)
+ if (!Tutorial::active || Tutorial::stage == 49)
if (hostile)
if (normaldotproduct(Person::players[i]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0 &&
distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 100 &&
}
OPENAL_SetFrequency(OPENAL_ALL, slomo);
- if (tutoriallevel == 1) {
- XYZ temp;
- XYZ temp2;
- XYZ temp3;
- XYZ oldtemp;
- XYZ oldtemp2;
- temp.x = 1011;
- temp.y = 84;
- temp.z = 491;
- temp2.x = 1025;
- temp2.y = 75;
- temp2.z = 447;
- temp3.x = 1038;
- temp3.y = 76;
- temp3.z = 453;
- oldtemp = temp;
- oldtemp2 = temp2;
- if (tutorialstage >= 51)
- if (distsq(&temp, &Person::players[0]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[0]->coords) < 4) {
- OPENAL_StopSound(OPENAL_ALL); // hack...OpenAL renderer isn't stopping music after tutorial goes to level menu...
- OPENAL_SetFrequency(OPENAL_ALL);
-
- emit_stream_np(stream_menutheme);
-
- gameon = 0;
- mainmenu = 5;
-
- fireSound();
-
- flash();
- }
- if (tutorialstage < 51)
- if (distsq(&temp, &Person::players[0]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[0]->coords) < 4) {
- emit_sound_at(fireendsound, Person::players[0]->coords);
-
- Person::players[0]->coords = (oldtemp + oldtemp2) / 2;
-
- flash();
- }
- if (tutorialstage >= 14 && tutorialstage < 50)
- if (distsq(&temp, &Person::players[1]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[1]->coords) < 4) {
- emit_sound_at(fireendsound, Person::players[1]->coords);
-
- for (unsigned i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
- if (Random() % 2 == 0) {
- if (!Person::players[1]->skeleton.free)
- temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
- if (Person::players[1]->skeleton.free)
- temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
- if (!Person::players[1]->skeleton.free)
- temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
- if (Person::players[1]->skeleton.free)
- temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
- Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
- }
- }
-
- Person::players[1]->coords = (oldtemp + oldtemp2) / 2;
- for (unsigned i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
- Person::players[1]->skeleton.joints[i].velocity = 0;
- if (Random() % 2 == 0) {
- if (!Person::players[1]->skeleton.free)
- temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
- if (Person::players[1]->skeleton.free)
- temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
- if (!Person::players[1]->skeleton.free)
- temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
- if (Person::players[1]->skeleton.free)
- temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
- Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
- }
- }
- }
+ if (Tutorial::active) {
+ Tutorial::DoStuff(multiplier);
}
maxalarmed = numalarmed;
}
- if (changedelay <= 0 && !loading && !editorenabled && gameon && !tutoriallevel && changedelay != -999 && !won) {
+ if (changedelay <= 0 && !loading && !editorenabled && gameon && !Tutorial::active && changedelay != -999 && !won) {
if (Person::players[0]->dead && changedelay <= 0) {
changedelay = 1;
targetlevel = whichlevel;
float slomospeed = 0;
float slomofreq = 0;
-int tutoriallevel = 0;
-int tutorialstage = 0;
-float tutorialstagetime = 0;
-float tutorialmaxtime = 0;
-float tutorialsuccess = 0;
-
bool againbonus = false;
float damagedealt = 0;
#include "Level/Awards.hpp"
#include "Level/Dialog.hpp"
#include "Utils/Folders.hpp"
+#include "Tutorial.hpp"
extern float multiplier;
extern Terrain terrain;
extern bool winfreeze;
extern bool showpoints;
extern bool immediate;
-extern int tutoriallevel;
extern float smoketex;
-extern int tutorialstage;
extern bool reversaltrain;
extern bool canattack;
extern bool cananger;
victim->spurt = 1;
DoBlood(.2, 250);
- if (tutoriallevel != 1)
+ if (!Tutorial::active)
emit_sound_at(heavyimpactsound, victim->coords);
victim->RagDoll(0);
for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
// FIXME: should abstract out inputs
static int bleedxint, bleedyint;
static XYZ bloodvel;
- if (bloodtoggle && tutoriallevel != 1) {
+ if (bloodtoggle && !Tutorial::active) {
if (bleeding <= 0 && spurt) {
spurt = 0;
for (int i = 0; i < 3; i++) {
if (howmuch && id == 0)
blooddimamount = 1;
- if (tutoriallevel != 1 || id == 0)
+ if (!Tutorial::active || id == 0)
if (aitype != playercontrolled && howmuch > 0) {
// play pain sounds
int whichsound = -1;
Game::flash(.5, 0);
}
- if (bloodtoggle && decals && tutoriallevel != 1) {
+ if (bloodtoggle && decals && !Tutorial::active) {
if (bleeding <= 0 && spurt) {
spurt = 0;
for (int i = 0; i < 3; i++) {
deathbleeding += bleeding;
bloodloss += bleeding * 3;
- if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
+ if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
if (abs(Random() % 2) == 0) {
aitype = gethelptype;
lastseentime = 12;
float coordsx, coordsy;
float total;
- if (bloodtoggle && decals && tutoriallevel != 1) {
+ if (bloodtoggle && decals && !Tutorial::active) {
where -= coords;
if (!skeleton.free)
where = DoRotation(where, 0, -yaw, 0);
deathbleeding += bleeding;
bloodloss += bleeding * 3;
- if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
+ if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
if (abs(Random() % 2) == 0) {
aitype = gethelptype;
lastseentime = 12;
|| staggerdelay <= 0)
&& victim->animTarget != jumpupanim
&& victim->animTarget != jumpdownanim
- && (tutoriallevel != 1 || cananger)
+ && (!Tutorial::active || cananger)
&& hostile))
return;
void Person::DoDamage(float howmuch)
{
// subtract health (temporary?)
- if (tutoriallevel != 1)
+ if (!Tutorial::active)
damage += howmuch / power;
// stats?
if (id != 0)
if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
bonus = 0;
// subtract health
- if (tutoriallevel != 1)
+ if (!Tutorial::active)
permanentdamage += howmuch / 2 / power;
- if (tutoriallevel != 1)
+ if (!Tutorial::active)
superpermanentdamage += howmuch / 4 / power;
// visual effects
if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
blackout = 1;
// cancel attack?
- if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
+ if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile))
aitype = attacktypecutoff;
- if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
+ if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
if (abs(Random() % 2) == 0) {
aitype = gethelptype;
lastseentime = 12;
}
// play sounds
- if (tutoriallevel != 1 || id == 0)
+ if (!Tutorial::active || id == 0)
if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
int whichsound = -1;
drawtogglekeydown = 1;
}
//Footstep sounds
- if (tutoriallevel != 1 || id == 0)
+ if (!Tutorial::active || id == 0)
if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
int whichsound = -1;
if (onterrain) {
} else if (targetFrame().label == 4) {
whichsound = knifeswishsound;
}
- if (targetFrame().label == 8 && tutoriallevel != 1) {
+ if (targetFrame().label == 8 && !Tutorial::active) {
whichsound = landsound2;
}
}
//Combat sounds
- if (tutoriallevel != 1 || id == 0)
+ if (!Tutorial::active || id == 0)
if (speechdelay <= 0)
if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
if (creature == wolftype)
DoBloodBig(0, 250);
}
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, victim->coords, 128.);
}
if (creature == wolftype) {
camerashake += .4;
victim->spurt = 1;
DoBlood(.2, 250);
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, victim->coords, 160.);
}
if (creature == wolftype) {
camerashake += .4;
victim->spurt = 1;
DoBlood(.2, 250);
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, victim->coords, 160.);
}
if (creature == wolftype) {
escapednum = 0;
if (id == 0)
camerashake += .4;
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, coords, 128.);
}
XYZ relative;
escapednum = 0;
if (id == 0)
camerashake += .4;
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(thudsound, coords);
}
victim->spurt = 1;
DoBlood(.2, 235);
}
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, victim->coords, 128);
}
if (id == 0)
camerashake += .4;
if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(thudsound, victim->coords);
}
} else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(whooshhitsound, victim->coords);
}
} else {
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, victim->coords);
}
}
if (hasvictim)
if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
escapednum = 0;
- if (tutoriallevel != 1)
+ if (!Tutorial::active)
victim->DoBloodBig(1.5 / victim->armorhigh, 225);
award_bonus(id, Slicebonus);
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(knifeslicesound, victim->coords);
}
//victim->jointVel(abdomen)+=relative*damagemult*200;
if (aitype != playercontrolled)
weaponmissdelay = .6;
- if (tutoriallevel != 1)
+ if (!Tutorial::active)
if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
weapons[weaponids[weaponactive]].bloody = 1;
- if (tutoriallevel != 1)
+ if (!Tutorial::active)
weapons[weaponids[weaponactive]].blooddrip += 3;
XYZ footvel, footpoint;
} else {
footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
}
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
if (bloodtoggle)
Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
footvel = DoRotation(facing, 0, 90, 0) * .8;
Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
}
- if (tutoriallevel == 1) {
+ if (Tutorial::active) {
Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
}
victim->DoDamage(damagemult * 0);
if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
award_bonus(id, Slashbonus);
escapednum = 0;
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
victim->DoBloodBig(2 / victim->armorhigh, 190);
else
emit_sound_at(swordslicesound, victim->coords);
}
//victim->jointVel(abdomen)+=relative*damagemult*200;
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
victim->frameTarget = 0;
victim->animTarget = staggerbackhardanim;
victim->targetyaw = targetyaw + 180;
victim->target = 0;
}
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
weapons[weaponids[weaponactive]].bloody = 1;
weapons[weaponids[weaponactive]].blooddrip += 3;
if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
escapednum = 0;
if (id == 0)
victim->jointVel(head) += relative * damagemult * 230;
victim->jointVel(neck) += relative * damagemult * 230;
victim->Puff(head);
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
victim->DoDamage(damagemult * 120 / victim->protectionhigh);
award_bonus(id, solidhit, 30);
if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
escapednum = 0;
if (id == 0)
victim->jointVel(head) += relative * damagemult * 220;
victim->jointVel(neck) += relative * damagemult * 220;
victim->Puff(head);
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
victim->DoDamage(damagemult * 350 / victim->protectionhead);
award_bonus(id, solidhit, 60);
if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
escapednum = 0;
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
if (!victim->dead)
weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
if (id == 0)
}
}
victim->Puff(abdomen);
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
victim->DoDamage(damagemult * 100 / victim->protectionhigh);
if (!victim->dead) {
victim->skeleton.joints[i].velocity += relative * damagemult * 40;
}
victim->jointVel(head) += relative * damagemult * 200;
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, victim->coords, 128.);
}
victim->Puff(head);
victim->animTarget = staggerbackhighanim;
victim->targetyaw = targetyaw + 180;
victim->target = 0;
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(landsound2, victim->coords, 128.);
}
victim->Puff(abdomen);
escapednum = 0;
if (id == 0)
camerashake += .2;
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(landsound2, victim->coords, 128.);
}
XYZ relative;
victim->animTarget = staggerbackhighanim;
victim->targetyaw = targetyaw + 180;
victim->target = 0;
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(landsound2, victim->coords, 128.);
}
victim->Puff(abdomen);
victim->spurt = 1;
DoBlood(.2, 230);
}
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, victim->coords, 128.);
}
if (creature == wolftype) {
award_bonus(id, staffreversebonus);
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, victim->coords, 128.);
}
victim->RagDoll(0);
victim->spurt = 1;
DoBlood(.2, 230);
}
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, victim->coords, 128.);
}
victim->RagDoll(0);
DoBlood(.2, 240);
}
if (weaponactive == -1) {
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
emit_sound_at(heavyimpactsound, victim->coords, 128.);
}
}
Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
}
- while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
+ while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
flamedelay += .05;
int howmany = fabs(Random() % (skeleton.joints.size()));
if (skeleton.free) {
if (hasvictim)
if (aitype != passivetype && victim->skeleton.free && !victim->dead)
play = 1;
- if (tutoriallevel == 1 && id != 0)
+ if (Tutorial::active && id != 0)
play = 0;
if (play && aitype != playercontrolled) {
int whichsound = -1;
glEnable(GL_LIGHTING);
glEnable(GL_BLEND);
}
- if (tutoriallevel && id != 0) {
+ if (Tutorial::active && id != 0) {
glColor4f(.7, .7, .7, 0.6);
glDepthMask(0);
glEnable(GL_LIGHTING);
}
if (playerdetail) {
if (!showpoints) {
- if ((tutoriallevel && id != 0))
+ if (Tutorial::active && (id != 0))
skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
else
skeleton.drawmodel.draw();
}
}
if (!playerdetail) {
- if ((tutoriallevel && id != 0))
+ if (Tutorial::active && (id != 0))
skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
else
skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
}
if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
- if (tutoriallevel && id != 0) {
+ if (Tutorial::active && id != 0) {
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glTranslatef(smoketex * .6, 0, 0);
if (playerdetail) {
if (!showpoints) {
- if ((tutoriallevel && id != 0))
+ if (Tutorial::active && (id != 0))
skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
else
skeleton.drawmodel.draw();
}
}
if (!playerdetail) {
- if ((tutoriallevel && id != 0))
+ if (Tutorial::active && (id != 0))
skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
else
skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
}
- if (tutoriallevel && id != 0) {
+ if (Tutorial::active && id != 0) {
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
#include "Audio/Sounds.hpp"
#include "Game.hpp"
#include "Level/Awards.hpp"
+#include "Tutorial.hpp"
extern float multiplier;
extern Terrain terrain;
extern float viewdistance;
extern float blackout;
extern bool freeze;
-extern int tutoriallevel;
extern int numthrowkill;
Model Weapon::throwingknifemodel;
Person::players[j]->jointVel(neck) += velocity * 2;
Person::players[j]->jointVel(rightshoulder) += velocity * 2;
Person::players[j]->jointVel(leftshoulder) += velocity * 2;
- if (bloodtoggle && tutoriallevel != 1)
+ if (bloodtoggle && !Tutorial::active)
Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
- if (tutoriallevel == 1)
+ if (Tutorial::active)
Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .8, .3);
footvel = tippoint - position;
Normalise(&footvel);
- if (bloodtoggle && tutoriallevel != 1)
+ if (bloodtoggle && !Tutorial::active)
Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * -1, 1, 0, 0, .6, 1);
- if (tutoriallevel != 1) {
+ if (!Tutorial::active) {
if (Person::players[j]->weaponstuckwhere == 0)
Person::players[j]->DoBloodBig(2, 205);
if (Person::players[j]->weaponstuckwhere == 1)
--- /dev/null
+/*
+Copyright (C) 2003, 2010 - Wolfire Games
+Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
+
+This file is part of Lugaru.
+
+Lugaru is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+Lugaru is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "Tutorial.hpp"
+#include "Game.hpp"
+#include "Audio/Sounds.hpp"
+#include "Audio/openal_wrapper.hpp"
+#include "Level/Awards.hpp"
+#include "Objects/Person.hpp"
+#include "Utils/Input.hpp"
+
+extern bool reversaltrain;
+extern bool canattack;
+extern bool cananger;
+extern int bonus;
+extern float damagedealt;
+extern bool againbonus;
+extern float screenwidth, screenheight;
+extern int mainmenu;
+
+bool Tutorial::active = false;
+int Tutorial::stage = 0;
+float Tutorial::stagetime = 0;
+float Tutorial::maxtime = 0;
+float Tutorial::success = 0;
+
+void Tutorial::Do(float multiplier)
+{
+ if (stagetime > maxtime) {
+ stage++;
+ success = 0;
+ if (stage <= 1) {
+ canattack = 0;
+ cananger = 0;
+ reversaltrain = 0;
+ }
+ switch (stage) {
+ case 1:
+ maxtime = 5;
+ break;
+ case 2:
+ case 10:
+ case 13:
+ case 26:
+ maxtime = 2;
+ break;
+ case 3:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ maxtime = 600;
+ break;
+ case 4:
+ case 11:
+ case 12:
+ maxtime = 1000;
+ break;
+ case 14: {
+ maxtime = 3;
+
+ XYZ temp, temp2;
+
+ temp.x = 1011;
+ temp.y = 84;
+ temp.z = 491;
+ temp2.x = 1025;
+ temp2.y = 75;
+ temp2.z = 447;
+
+ Person::players[1]->coords = (temp + temp2) / 2;
+
+ emit_sound_at(fireendsound, Person::players[1]->coords);
+
+ for (unsigned i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
+ if (Random() % 2 == 0) {
+ if (!Person::players[1]->skeleton.free)
+ temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
+ if (Person::players[1]->skeleton.free)
+ temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
+ if (!Person::players[1]->skeleton.free)
+ temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
+ if (Person::players[1]->skeleton.free)
+ temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
+ Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
+ }
+ }
+ }
+ break;
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 20:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ maxtime = 500;
+ break;
+ case 19:
+ stage = 20;
+ break;
+ case 21:
+ maxtime = 500;
+ if (bonus == cannon) {
+ bonus = Slicebonus;
+ againbonus = 1;
+ } else
+ againbonus = 0;
+ break;
+ case 27:
+ maxtime = 4;
+ reversaltrain = 1;
+ cananger = 1;
+ Person::players[1]->aitype = attacktypecutoff;
+ break;
+ case 28:
+ case 34:
+ case 35:
+ maxtime = 400;
+ break;
+ case 29:
+ maxtime = 400;
+ Person::players[0]->escapednum = 0;
+ break;
+ case 30:
+ maxtime = 4;
+ reversaltrain = 0;
+ cananger = 0;
+ Person::players[1]->aitype = passivetype;
+ break;
+ case 31:
+ maxtime = 13;
+ break;
+ case 32:
+ maxtime = 8;
+ break;
+ case 33:
+ maxtime = 400;
+ cananger = 1;
+ canattack = 1;
+ Person::players[1]->aitype = attacktypecutoff;
+ break;
+ case 36:
+ maxtime = 2;
+ reversaltrain = 0;
+ cananger = 0;
+ Person::players[1]->aitype = passivetype;
+ break;
+ case 37:
+ damagedealt = 0;
+ damagetaken = 0;
+ maxtime = 50;
+ cananger = 1;
+ canattack = 1;
+ Person::players[1]->aitype = attacktypecutoff;
+ break;
+ case 38:
+ maxtime = 4;
+ canattack = 0;
+ cananger = 0;
+ Person::players[1]->aitype = passivetype;
+ break;
+ case 39: {
+ XYZ temp, temp2;
+
+ temp.x = 1011;
+ temp.y = 84;
+ temp.z = 491;
+ temp2.x = 1025;
+ temp2.y = 75;
+ temp2.z = 447;
+
+ Weapon w(knife, -1);
+ w.position = (temp + temp2) / 2;
+ w.tippoint = (temp + temp2) / 2;
+
+ w.velocity = 0.1;
+ w.tipvelocity = 0.1;
+ w.missed = 1;
+ w.hitsomething = 0;
+ w.freetime = 0;
+ w.firstfree = 1;
+ w.physics = 1;
+
+ weapons.push_back(w);
+ }
+ break;
+ case 40:
+ case 41:
+ case 43:
+ maxtime = 300;
+ break;
+ case 42:
+ maxtime = 8;
+ break;
+ case 44:
+ weapons[0].owner = 1;
+ Person::players[0]->weaponactive = -1;
+ Person::players[0]->num_weapons = 0;
+ Person::players[1]->weaponactive = 0;
+ Person::players[1]->num_weapons = 1;
+ Person::players[1]->weaponids[0] = 0;
+
+ cananger = 1;
+ canattack = 1;
+ Person::players[1]->aitype = attacktypecutoff;
+
+ maxtime = 300;
+ break;
+ case 45:
+ weapons[0].owner = 1;
+ Person::players[0]->weaponactive = -1;
+ Person::players[0]->num_weapons = 0;
+ Person::players[1]->weaponactive = 0;
+ Person::players[1]->num_weapons = 1;
+ Person::players[1]->weaponids[0] = 0;
+
+ maxtime = 300;
+ break;
+ case 46:
+ weapons[0].owner = 1;
+ Person::players[0]->weaponactive = -1;
+ Person::players[0]->num_weapons = 0;
+ Person::players[1]->weaponactive = 0;
+ Person::players[1]->num_weapons = 1;
+ Person::players[1]->weaponids[0] = 0;
+
+ weapons[0].setType(sword);
+
+ maxtime = 300;
+ break;
+ case 47: {
+ maxtime = 10;
+
+ XYZ temp, temp2;
+
+ temp.x = 1011;
+ temp.y = 84;
+ temp.z = 491;
+ temp2.x = 1025;
+ temp2.y = 75;
+ temp2.z = 447;
+
+ Weapon w(sword, -1);
+ w.position = (temp + temp2) / 2;
+ w.tippoint = (temp + temp2) / 2;
+
+ w.velocity = 0.1;
+ w.tipvelocity = 0.1;
+ w.missed = 1;
+ w.hitsomething = 0;
+ w.freetime = 0;
+ w.firstfree = 1;
+ w.physics = 1;
+
+ weapons.push_back(w);
+
+ weapons[0].owner = 1;
+ weapons[1].owner = 0;
+ Person::players[0]->weaponactive = 0;
+ Person::players[0]->num_weapons = 1;
+ Person::players[0]->weaponids[0] = 1;
+ Person::players[1]->weaponactive = 0;
+ Person::players[1]->num_weapons = 1;
+ Person::players[1]->weaponids[0] = 0;
+
+ }
+ break;
+ case 48:
+ canattack = 0;
+ cananger = 0;
+ Person::players[1]->aitype = passivetype;
+
+ maxtime = 15;
+
+ weapons[0].owner = 1;
+ weapons[1].owner = 0;
+ Person::players[0]->weaponactive = 0;
+ Person::players[0]->num_weapons = 1;
+ Person::players[0]->weaponids[0] = 1;
+ Person::players[1]->weaponactive = 0;
+ Person::players[1]->num_weapons = 1;
+ Person::players[1]->weaponids[0] = 0;
+
+ if (Person::players[0]->weaponactive != -1)
+ weapons[Person::players[0]->weaponids[Person::players[0]->weaponactive]].setType(staff);
+ else
+ weapons[0].setType(staff);
+ break;
+ case 49:
+ canattack = 0;
+ cananger = 0;
+ Person::players[1]->aitype = passivetype;
+
+ maxtime = 200;
+
+ weapons[1].position = 1000;
+ weapons[1].tippoint = 1000;
+
+ weapons[0].setType(knife);
+
+ weapons[0].owner = 0;
+ Person::players[1]->weaponactive = -1;
+ Person::players[1]->num_weapons = 0;
+ Person::players[0]->weaponactive = 0;
+ Person::players[0]->num_weapons = 1;
+ Person::players[0]->weaponids[0] = 0;
+
+ break;
+ case 50: {
+ maxtime = 8;
+
+ XYZ temp, temp2;
+ emit_sound_at(fireendsound, Person::players[1]->coords);
+
+ for (unsigned i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
+ if (Random() % 2 == 0) {
+ if (!Person::players[1]->skeleton.free)
+ temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
+ if (Person::players[1]->skeleton.free)
+ temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
+ if (!Person::players[1]->skeleton.free)
+ temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
+ if (Person::players[1]->skeleton.free)
+ temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
+ Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
+ }
+ }
+
+ Person::players[1]->num_weapons = 0;
+ Person::players[1]->weaponstuck = -1;
+ Person::players[1]->weaponactive = -1;
+
+ weapons.clear();
+ }
+ break;
+ case 51:
+ maxtime = 80000;
+ break;
+ default:
+ break;
+ }
+ if (stage <= 51)
+ stagetime = 0;
+ }
+
+ //Tutorial success
+ if (stagetime < maxtime - 3) {
+ switch (stage) {
+ case 3:
+ if (Game::deltah || Game::deltav)
+ success += multiplier;
+ break;
+ case 4:
+ if (Person::players[0]->forwardkeydown || Person::players[0]->backkeydown || Person::players[0]->leftkeydown || Person::players[0]->rightkeydown)
+ success += multiplier;
+ break;
+ case 5:
+ if (Person::players[0]->jumpkeydown)
+ success = 1;
+ break;
+ case 6:
+ if (Person::players[0]->isCrouch())
+ success = 1;
+ break;
+ case 7:
+ if (Person::players[0]->animTarget == rollanim)
+ success = 1;
+ break;
+ case 8:
+ if (Person::players[0]->animTarget == sneakanim)
+ success += multiplier;
+ break;
+ case 9:
+ if (Person::players[0]->animTarget == rabbitrunninganim || Person::players[0]->animTarget == wolfrunninganim)
+ success += multiplier;
+ break;
+ case 11:
+ if (Person::players[0]->isWallJump())
+ success = 1;
+ break;
+ case 12:
+ if (Person::players[0]->animTarget == flipanim)
+ success = 1;
+ break;
+ case 15:
+ if (Person::players[0]->animTarget == upunchanim || Person::players[0]->animTarget == winduppunchanim)
+ success = 1;
+ break;
+ case 16:
+ if (Person::players[0]->animTarget == winduppunchanim)
+ success = 1;
+ break;
+ case 17:
+ if (Person::players[0]->animTarget == spinkickanim)
+ success = 1;
+ break;
+ case 18:
+ if (Person::players[0]->animTarget == sweepanim)
+ success = 1;
+ break;
+ case 19:
+ if (Person::players[0]->animTarget == dropkickanim)
+ success = 1;
+ break;
+ case 20:
+ if (Person::players[0]->animTarget == rabbitkickanim)
+ success = 1;
+ break;
+ case 21:
+ if (bonus == cannon)
+ success = 1;
+ break;
+ case 22:
+ if (bonus == spinecrusher)
+ success = 1;
+ break;
+ case 23:
+ if (Person::players[0]->animTarget == walljumprightkickanim || Person::players[0]->animTarget == walljumpleftkickanim)
+ success = 1;
+ break;
+ case 24:
+ if (Person::players[0]->animTarget == rabbittacklinganim)
+ success = 1;
+ break;
+ case 25:
+ if (Person::players[0]->animTarget == backhandspringanim)
+ success = 1;
+ break;
+ case 28:
+ if (Animation::animations[Person::players[0]->animTarget].attack == reversed && Person::players[0]->feint)
+ success = 1;
+ break;
+ case 29:
+ if (Person::players[0]->escapednum == 2) {
+ success = 1;
+ reversaltrain = 0;
+ cananger = 0;
+ Person::players[1]->aitype = passivetype;
+ }
+ break;
+ case 33:
+ case 34:
+ if (Animation::animations[Person::players[0]->animTarget].attack == reversal) {
+ success = 1;
+ }
+ break;
+ case 35:
+ if (Animation::animations[Person::players[0]->animTarget].attack == reversal) {
+ success = 1;
+ reversaltrain = 0;
+ cananger = 0;
+ Person::players[1]->aitype = passivetype;
+ }
+ break;
+ case 40:
+ if (Person::players[0]->num_weapons > 0) {
+ success = 1;
+ }
+ break;
+ case 41:
+ if (Person::players[0]->weaponactive == -1 && Person::players[0]->num_weapons > 0) {
+ success = 1;
+ }
+ break;
+ case 43:
+ if (Person::players[0]->animTarget == knifeslashstartanim) {
+ success = 1;
+ }
+ break;
+ case 44:
+ case 45:
+ case 46:
+ if (Animation::animations[Person::players[0]->animTarget].attack == reversal) {
+ success = 1;
+ }
+ break;
+ case 49:
+ if (Person::players[1]->weaponstuck != -1) {
+ success = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ if (success >= 1) {
+ stagetime = maxtime - 3;
+ }
+
+ if (stagetime == maxtime - 3) {
+ emit_sound_np(consolesuccesssound);
+ }
+
+ if (success >= 1) {
+ if (stage == 34 || stage == 35) {
+ stagetime = maxtime - 1;
+ }
+ }
+ }
+
+ if (stage < 14 || stage >= 50) {
+ Person::players[1]->coords.y = 300;
+ Person::players[1]->velocity = 0;
+ }
+}
+
+void Tutorial::DrawText()
+{
+ std::string string;
+ std::string string2;
+ std::string string3;
+ float tutorialopac = maxtime - stagetime;
+ if (tutorialopac > 1)
+ tutorialopac = 1;
+ if (tutorialopac < 0)
+ tutorialopac = 0;
+
+ string = " ";
+ string2 = " ";
+ string3 = " ";
+ if (stage == 0) {
+ string = " ";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 1) {
+ string = "Welcome to the Lugaru training level!";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 2) {
+ string = "BASIC MOVEMENT:";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 3) {
+ string = "You can move the mouse to rotate the camera.";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 4) {
+ string = std::string("Try using the ") +
+ Input::keyToChar(Game::forwardkey) + ", " +
+ Input::keyToChar(Game::leftkey) + ", " +
+ Input::keyToChar(Game::backkey) + " and " +
+ Input::keyToChar(Game::rightkey) + " keys to move around.";
+ string2 = "All movement is relative to the camera.";
+ string3 = " ";
+ }
+ if (stage == 5) {
+ string = std::string("Please press ") + Input::keyToChar(Game::jumpkey) + " to jump.";
+ string2 = "You can hold it longer to jump higher.";
+ string3 = " ";
+ }
+ if (stage == 6) {
+ string = std::string("You can press ") + Input::keyToChar(Game::crouchkey) + " to crouch.";
+ string2 = "You can jump higher from a crouching position.";
+ string3 = " ";
+ }
+ if (stage == 7) {
+ string = std::string("While running, you can press ") + Input::keyToChar(Game::crouchkey) + " to roll.";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 8) {
+ string = "While crouching, you can sneak around silently";
+ string2 = "using the movement keys.";
+ string3 = " ";
+ }
+ if (stage == 9) {
+ string = "Release the crouch key while sneaking and hold the movement keys";
+ string2 = "to run animal-style.";
+ string3 = " ";
+ }
+ if (stage == 10) {
+ string = "ADVANCED MOVEMENT:";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 11) {
+ string = std::string("When you jump at a wall, you can hold ") + Input::keyToChar(Game::jumpkey) + " again";
+ string2 = "during impact to perform a walljump.";
+ string3 = "Be sure to use the movement keys to press against the wall";
+ }
+ if (stage == 12) {
+ string = "While in the air, you can press crouch to flip.";
+ string2 = "Walljumps and flips confuse enemies and give you more control.";
+ string3 = " ";
+ }
+ if (stage == 13) {
+ string = "BASIC COMBAT:";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 14) {
+ string = "There is now an imaginary enemy";
+ string2 = "in the middle of the training area.";
+ string3 = " ";
+ }
+ if (stage == 15) {
+ if (Game::attackkey == MOUSEBUTTON1) {
+ string = "Click to attack when you are near an enemy.";
+ } else {
+ string = std::string("Press ") + Input::keyToChar(Game::attackkey) + " to attack when you are near an enemy.";
+ }
+ string2 = "You can punch by standing still near an enemy and attacking.";
+ string3 = " ";
+ }
+ if (stage == 16) {
+ string = "If you are close, you will perform a weak punch.";
+ string2 = "The weak punch is excellent for starting attack combinations.";
+ string3 = " ";
+ }
+ if (stage == 17) {
+ string = "Attacking while running results in a spin kick.";
+ string2 = "This is one of your most powerful ground attacks.";
+ string3 = " ";
+ }
+ if (stage == 18) {
+ string = "Sweep the enemy's legs out by attacking while crouched.";
+ string2 = "This is a very fast attack, and easy to follow up.";
+ string3 = " ";
+ }
+ if (stage == 19) {
+ string = "When an enemy is on the ground, you can deal some extra";
+ string2 = "damage by running up and drop-kicking him.";
+ string3 = "(Try knocking them down with a sweep first)";
+ }
+ if (stage == 20) {
+ string = "Your most powerful individual attack is the rabbit kick.";
+ if (Game::attackkey == MOUSEBUTTON1) {
+ string2 = "Run at the enemy while holding the mouse button, and press";
+ } else {
+ string2 = std::string("Run at the enemy while holding ") + Input::keyToChar(Game::attackkey) + ", and press";
+ }
+ string3 = std::string("the jump key (") + Input::keyToChar(Game::jumpkey) + ") to attack.";
+ }
+ if (stage == 21) {
+ string = "This attack is devastating if timed correctly.";
+ string2 = "Even if timed incorrectly, it will knock the enemy over.";
+ if (againbonus)
+ string3 = "Try rabbit-kicking the imaginary enemy again.";
+ else
+ string3 = "Try rabbit-kicking the imaginary enemy.";
+ }
+ if (stage == 22) {
+ string = "If you sneak behind an enemy unnoticed, you can kill";
+ string2 = "him instantly. Move close behind this enemy";
+ string3 = "and attack.";
+ }
+ if (stage == 23) {
+ string = "Another important attack is the wall kick. When an enemy";
+ string2 = "is near a wall, perform a walljump nearby and hold";
+ string3 = "the attack key during impact with the wall.";
+ }
+ if (stage == 24) {
+ string = "You can tackle enemies by running at them animal-style";
+ if (Game::attackkey == MOUSEBUTTON1) {
+ string2 = std::string("and pressing jump (") + Input::keyToChar(Game::jumpkey) + ") or attack(mouse button).";
+ } else {
+ string2 = std::string("and pressing jump (") + Input::keyToChar(Game::jumpkey) + ") or attack(" + Input::keyToChar(Game::attackkey) + ").";
+ }
+ string3 = "This is especially useful when they are running away.";
+ }
+ if (stage == 25) {
+ string = "Dodge by pressing back and attack. Dodging is essential";
+ string2 = "against enemies with swords or other long weapons.";
+ string3 = " ";
+ }
+ if (stage == 26) {
+ string = "REVERSALS AND COUNTER-REVERSALS";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 27) {
+ string = "The enemy can now reverse your attacks.";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 28) {
+ string = "If you attack, you will notice that the enemy now sometimes";
+ string2 = "catches your attack and uses it against you. Hold";
+ string3 = std::string("crouch (") + Input::keyToChar(Game::crouchkey) + ") after attacking to escape from reversals.";
+ }
+ if (stage == 29) {
+ string = "Try escaping from two more reversals in a row.";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 30) {
+ string = "Good!";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 31) {
+ string = std::string("To reverse an attack, you must tap crouch (") + Input::keyToChar(Game::crouchkey) + ") during the";
+ string2 = "enemy's attack. You must also be close to the enemy;";
+ string3 = "this is especially important against armed opponents.";
+ }
+ if (stage == 32) {
+ string = "The enemy can attack in " + to_string(int(maxtime - stagetime)) + " seconds.";
+ string2 = "This imaginary opponents attacks will be highlighted";
+ string3 = "to make this easier.";
+ }
+ if (stage == 33) {
+ string = "Reverse three enemy attacks!";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 34) {
+ string = "Reverse two more enemy attacks!";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 35) {
+ string = "Reverse one more enemy attack!";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 36) {
+ string = "Excellent!";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 37) {
+ string = "Now spar with the enemy for " + to_string(int(maxtime - stagetime)) + " more seconds.";
+ string2 = "Damage dealt: " + to_string(int(damagedealt));
+ string3 = "Damage taken: " + to_string(int(damagetaken));
+ }
+ if (stage == 38) {
+ string = "WEAPONS:";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 39) {
+ string = "There is now an imaginary knife";
+ string2 = "in the center of the training area.";
+ string3 = " ";
+ }
+ if (stage == 40) {
+ string = "Stand, roll or handspring over the knife";
+ string2 = std::string("while pressing ") + Input::keyToChar(Game::throwkey) + " to pick it up.";
+ string3 = "You can crouch and press the same key to drop it again.";
+ }
+ if (stage == 41) {
+ string = std::string("You can equip and unequip weapons using the ") + Input::keyToChar(Game::drawkey) + " key.";
+ string2 = "Sometimes it is best to keep them unequipped to";
+ string3 = "prevent enemies from taking them. ";
+ }
+ if (stage == 42) {
+ string = "The knife is the smallest weapon and the least encumbering.";
+ string2 = "You can equip or unequip it while standing, crouching,";
+ string3 = "running or flipping.";
+ }
+ if (stage == 43) {
+ string = "You perform weapon attacks the same way as unarmed attacks,";
+ string2 = "but sharp weapons cause permanent damage, instead of the";
+ string3 = "temporary trauma from blunt weapons, fists and feet.";
+ }
+ if (stage == 44) {
+ string = "The enemy now has your knife!";
+ string2 = "Please reverse two of his knife attacks.";
+ string3 = " ";
+ }
+ if (stage == 45) {
+ string = "Please reverse one more of his knife attacks.";
+ string2 = " ";
+ string3 = " ";
+ }
+ if (stage == 46) {
+ string = "Now he has a sword!";
+ string2 = "The sword has longer reach than your arms, so you";
+ string3 = "must move close to reverse the sword slash.";
+ }
+ if (stage == 47) {
+ string = "Long weapons like the sword and staff are also useful for defense;";
+ string2 = "you can parry enemy weapon attacks by pressing the attack key";
+ string3 = "at the right time. Please try parrying the enemy's attacks!";
+ }
+ if (stage == 48) {
+ string = "The staff is like the sword, but has two main attacks.";
+ string2 = "The standing smash is fast and effective, and the running";
+ string3 = "spin smash is slower and more powerful.";
+ }
+ if (stage == 49) {
+ string = std::string("When facing an enemy, you can throw the knife with ") + Input::keyToChar(Game::throwkey) + ".";
+ string2 = "It is possible to throw the knife while flipping,";
+ string3 = "but it is very inaccurate.";
+ }
+ if (stage == 50) {
+ string = "You now know everything you can learn from training.";
+ string2 = "Everything else you must learn from experience!";
+ string3 = " ";
+ }
+ if (stage == 51) {
+ string = "Walk out of the training area to return to the main menu.";
+ string2 = " ";
+ string3 = " ";
+ }
+
+ Game::text->glPrintOutlined(1, 1, 1, tutorialopac, screenwidth / 2 - 7.6 * string.size()*screenwidth / 1024, screenheight / 16 + screenheight * 4 / 5, string, 1, 1.5 * screenwidth / 1024, screenwidth, screenheight);
+ Game::text->glPrintOutlined(1, 1, 1, tutorialopac, screenwidth / 2 - 7.6 * string2.size()*screenwidth / 1024, screenheight / 16 + screenheight * 4 / 5 - 20 * screenwidth / 1024, string2, 1, 1.5 * screenwidth / 1024, screenwidth, screenheight);
+ Game::text->glPrintOutlined(1, 1, 1, tutorialopac, screenwidth / 2 - 7.6 * string3.size()*screenwidth / 1024, screenheight / 16 + screenheight * 4 / 5 - 40 * screenwidth / 1024, string3, 1, 1.5 * screenwidth / 1024, screenwidth, screenheight);
+
+ string = "Press 'tab' to skip to the next item.";
+ string2 = "Press escape at any time to";
+ string3 = "pause or exit the tutorial.";
+
+ Game::text->glPrintOutlined(0.5, 0.5, 0.5, 1, screenwidth / 2 - 7.6 * string.size()*screenwidth / 1024 * .8, 0 + screenheight * 1 / 10, string, 1, 1.5 * screenwidth / 1024 * .8, screenwidth, screenheight);
+ Game::text->glPrintOutlined(0.5, 0.5, 0.5, 1, screenwidth / 2 - 7.6 * string2.size()*screenwidth / 1024 * .8, 0 + screenheight * 1 / 10 - 20 * .8 * screenwidth / 1024, string2, 1, 1.5 * screenwidth / 1024 * .8, screenwidth, screenheight);
+ Game::text->glPrintOutlined(0.5, 0.5, 0.5, 1, screenwidth / 2 - 7.6 * string3.size()*screenwidth / 1024 * .8, 0 + screenheight * 1 / 10 - 40 * .8 * screenwidth / 1024, string3, 1, 1.5 * screenwidth / 1024 * .8, screenwidth, screenheight);
+}
+
+void Tutorial::DoStuff(float multiplier)
+{
+ XYZ temp;
+ XYZ temp2;
+ XYZ temp3;
+ XYZ oldtemp;
+ XYZ oldtemp2;
+ temp.x = 1011;
+ temp.y = 84;
+ temp.z = 491;
+ temp2.x = 1025;
+ temp2.y = 75;
+ temp2.z = 447;
+ temp3.x = 1038;
+ temp3.y = 76;
+ temp3.z = 453;
+ oldtemp = temp;
+ oldtemp2 = temp2;
+ if (stage >= 51) {
+ if (distsq(&temp, &Person::players[0]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[0]->coords) < 4) {
+ OPENAL_StopSound(OPENAL_ALL); // hack...OpenAL renderer isn't stopping music after tutorial goes to level menu...
+ OPENAL_SetFrequency(OPENAL_ALL);
+
+ emit_stream_np(stream_menutheme);
+
+ Game::gameon = 0;
+ mainmenu = 5;
+
+ Game::fireSound();
+
+ Game::flash();
+ }
+ } else {
+ if (distsq(&temp, &Person::players[0]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[0]->coords) < 4) {
+ emit_sound_at(fireendsound, Person::players[0]->coords);
+
+ Person::players[0]->coords = (oldtemp + oldtemp2) / 2;
+
+ Game::flash();
+ }
+ }
+ if (stage >= 14 && stage < 50) {
+ if (distsq(&temp, &Person::players[1]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[1]->coords) < 4) {
+ emit_sound_at(fireendsound, Person::players[1]->coords);
+
+ for (unsigned i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
+ if (Random() % 2 == 0) {
+ if (!Person::players[1]->skeleton.free)
+ temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
+ if (Person::players[1]->skeleton.free)
+ temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
+ if (!Person::players[1]->skeleton.free)
+ temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
+ if (Person::players[1]->skeleton.free)
+ temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
+ Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
+ }
+ }
+
+ Person::players[1]->coords = (oldtemp + oldtemp2) / 2;
+ for (unsigned i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
+ Person::players[1]->skeleton.joints[i].velocity = 0;
+ if (Random() % 2 == 0) {
+ if (!Person::players[1]->skeleton.free)
+ temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
+ if (Person::players[1]->skeleton.free)
+ temp2 = Person::players[1]->skeleton.joints[i].velocity * Person::players[1]->scale / 2;
+ if (!Person::players[1]->skeleton.free)
+ temp = DoRotation(DoRotation(DoRotation(Person::players[1]->skeleton.joints[i].position, 0, 0, Person::players[1]->tilt), Person::players[1]->tilt2, 0, 0), 0, Person::players[1]->yaw, 0) * Person::players[1]->scale + Person::players[1]->coords;
+ if (Person::players[1]->skeleton.free)
+ temp = Person::players[1]->skeleton.joints[i].position * Person::players[1]->scale + Person::players[1]->coords;
+ Sprite::MakeSprite(breathsprite, temp, temp2, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+Copyright (C) 2003, 2010 - Wolfire Games
+Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
+
+This file is part of Lugaru.
+
+Lugaru is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+Lugaru is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _TUTORIAL_HPP_
+#define _TUTORIAL_HPP_
+
+class Tutorial
+{
+public:
+ static bool active;
+ static int stage;
+ static float stagetime;
+ static float maxtime;
+
+ static void Do(float multiplier);
+ static void DrawText();
+ static void DoStuff(float multiplier);
+
+private:
+ static float success;
+};
+
+#endif