X-Git-Url: https://git.jsancho.org/?a=blobdiff_plain;f=Source%2FObjects%2FPerson.cpp;h=a6f2bc199647fb3b763f41c36c6a85964a8986d9;hb=d3f16728298e0639a3b2e916386f4e8cea4018ff;hp=bc54a0df073f2b4a0491265f1dcf80ac0418c793;hpb=6cb245d6d347e0f610b2851d08273087fff9c0d0;p=lugaru.git diff --git a/Source/Objects/Person.cpp b/Source/Objects/Person.cpp index bc54a0d..a6f2bc1 100644 --- a/Source/Objects/Person.cpp +++ b/Source/Objects/Person.cpp @@ -27,6 +27,7 @@ along with Lugaru. If not, see . #include "Level/Awards.hpp" #include "Level/Dialog.hpp" #include "Utils/Folders.hpp" +#include "Tutorial.hpp" extern float multiplier; extern Terrain terrain; @@ -44,22 +45,19 @@ extern float realtexdetail; extern GLubyte bloodText[512 * 512 * 3]; extern GLubyte wolfbloodText[512 * 512 * 3]; extern int bloodtoggle; -extern Objects objects; extern bool autoslomo; extern float camerashake; extern float woozy; extern float viewdistance; extern float blackout; extern int difficulty; -extern bool decals; +extern bool decalstoggle; extern float fadestart; extern bool freeze; 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; @@ -69,6 +67,13 @@ extern float hostiletime; extern bool gamestarted; +extern XYZ envsound[30]; +extern float envsoundvol[30]; +extern int numenvsounds; +extern float envsoundlife[30]; + +extern XYZ windvector; + std::vector> Person::players(1, std::shared_ptr(new Person())); Person::Person() : @@ -480,7 +485,7 @@ void Person::CheckKick() 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++) { @@ -560,8 +565,8 @@ int Person::getIdle() { if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype)) return talkidleanim; - if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/) - if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype && + if (hasvictim && (victim != this->shared_from_this())) { + if ((!victim->dead && victim->aitype != passivetype && victim->aitype != searchtype && aitype != passivetype && aitype != searchtype && victim->id < Person::players.size())) { if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) { @@ -583,6 +588,7 @@ int Person::getIdle() if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) return fightsidestep; } + } if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) return hurtidleanim; if (howactive == typesitting) return sitanim; @@ -681,7 +687,7 @@ void Person::DoBlood(float howmuch, int which) // 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++) { @@ -723,7 +729,7 @@ void Person::DoBlood(float howmuch, int which) } } } - if (decals) { + if (decalstoggle) { // FIXME: manipulating attributes bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25; bleedxint = 0; @@ -761,7 +767,7 @@ void Person::DoBloodBig(float howmuch, int which) 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; @@ -791,7 +797,7 @@ void Person::DoBloodBig(float howmuch, int which) Game::flash(.5, 0); } - if (bloodtoggle && decals && tutoriallevel != 1) { + if (bloodtoggle && decalstoggle && !Tutorial::active) { if (bleeding <= 0 && spurt) { spurt = 0; for (int i = 0; i < 3; i++) { @@ -946,7 +952,7 @@ void Person::DoBloodBig(float howmuch, int which) 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; @@ -974,7 +980,7 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where) float coordsx, coordsy; float total; - if (bloodtoggle && decals && tutoriallevel != 1) { + if (bloodtoggle && decalstoggle && !Tutorial::active) { where -= coords; if (!skeleton.free) where = DoRotation(where, 0, -yaw, 0); @@ -990,9 +996,9 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where) if (whichtri != -1) { // low level geometry math p0 = colpoint; - p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]]; - p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]]; - p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]]; + p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0); + p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1); + p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2); bary.x = distsq(&p0, &p1); bary.y = distsq(&p0, &p2); @@ -1159,7 +1165,7 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where) 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; @@ -1184,7 +1190,7 @@ void Person::Reverse() || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim - && (tutoriallevel != 1 || cananger) + && (!Tutorial::active || cananger) && hostile)) return; @@ -1487,40 +1493,44 @@ void Person::Reverse() */ void Person::DoDamage(float howmuch) { - // subtract health (temporary?) - if (tutoriallevel != 1) - damage += howmuch / power; // stats? - if (id != 0) - damagedealt += howmuch / power; - if (id == 0) + if (id == 0) { damagetaken += howmuch / power; + } else { + damagedealt += howmuch / power; + } // reset bonuses - if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) + if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) { bonus = 0; + } + // subtract health - if (tutoriallevel != 1) + if (!Tutorial::active) { + damage += howmuch / power; permanentdamage += howmuch / 2 / power; - if (tutoriallevel != 1) superpermanentdamage += howmuch / 4 / power; + } // visual effects if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) DoBlood(1, 255); if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) DoBlood(1, 255); spurt = 0; - if (id == 0) + if (id == 0) { camerashake += howmuch / 100; - if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2))) - blackout = damage / damagetolerance; - if (blackout > 1) - blackout = 1; + if ((howmuch > 50 && damage > damagetolerance / 2)) { + blackout = damage / damagetolerance; + if (blackout > 1) { + 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; @@ -1561,7 +1571,7 @@ void Person::DoDamage(float howmuch) } // play sounds - if (tutoriallevel != 1 || id == 0) + if (!Tutorial::active || id == 0) { if (speechdelay <= 0 && !dead && aitype != playercontrolled) { int whichsound = -1; @@ -1585,6 +1595,7 @@ void Person::DoDamage(float howmuch) addEnvSound(coords); } } + } speechdelay = .3; } @@ -1689,7 +1700,7 @@ void Person::DoHead() void Person::RagDoll(bool checkcollision) { static XYZ change; - static int l, i; + static int i; static float speed; if (!skeleton.free) { if (id == 0) @@ -1772,34 +1783,32 @@ void Person::RagDoll(bool checkcollision) } if (checkcollision) { - XYZ average; XYZ lowpoint; XYZ colpoint; - int howmany; - average = 0; - howmany = 0; - for (unsigned j = 0; j < skeleton.joints.size(); j++) { - average += skeleton.joints[j].position; - howmany++; - } - average /= howmany; - coords += average * scale; - for (unsigned j = 0; j < skeleton.joints.size(); j++) { - skeleton.joints[j].position -= average; + if (!skeleton.joints.empty()) { + XYZ average; + average = 0; + for (unsigned j = 0; j < skeleton.joints.size(); j++) { + average += skeleton.joints[j].position; + } + average /= skeleton.joints.size(); + coords += average * scale; + for (unsigned j = 0; j < skeleton.joints.size(); j++) { + skeleton.joints[j].position -= average; + } } whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale); whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale); - if (terrain.patchobjectnum[whichpatchx][whichpatchz]) - for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) { - i = terrain.patchobjects[whichpatchx][whichpatchz][l]; - lowpoint = coords; - lowpoint.y += 1; - if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) { - coords.x = lowpoint.x; - coords.z = lowpoint.z; - } + for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) { + i = terrain.patchobjects[whichpatchx][whichpatchz][l]; + lowpoint = coords; + lowpoint.y += 1; + if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) { + coords.x = lowpoint.x; + coords.z = lowpoint.z; } + } } yaw = 0; @@ -1903,7 +1912,7 @@ void Person::Puff(int whichlabel) /* EFFECT * I think I added this in an attempt to clean up code */ -void Person::setAnimation(int animation) +void Person::setTargetAnimation(int animation) { animTarget = animation; frameTarget = 0; @@ -1936,7 +1945,7 @@ void Person::DoAnimations() vel[2] = velocity.z; if (id == 0) { - OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel); + OPENAL_3D_SetAttributes(channels[whooshsound], gLoc); OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5); } if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) @@ -2033,7 +2042,7 @@ void Person::DoAnimations() 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) { @@ -2081,7 +2090,7 @@ void Person::DoAnimations() } else if (targetFrame().label == 4) { whichsound = knifeswishsound; } - if (targetFrame().label == 8 && tutoriallevel != 1) { + if (targetFrame().label == 8 && !Tutorial::active) { whichsound = landsound2; } @@ -2106,7 +2115,7 @@ void Person::DoAnimations() } //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))) { @@ -2338,7 +2347,7 @@ void Person::DoAnimations() } if ((Animation::animations[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) { if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) { - if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) { + if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) { escapednum = 0; if (id == 0) camerashake += .4; @@ -2348,7 +2357,7 @@ void Person::DoAnimations() if (creature == wolftype) DoBloodBig(0, 250); } - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } if (creature == wolftype) { @@ -2374,7 +2383,7 @@ void Person::DoAnimations() } if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) { - if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) { + if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) { escapednum = 0; if (id == 0) camerashake += .4; @@ -2413,7 +2422,7 @@ void Person::DoAnimations() camerashake += .4; victim->spurt = 1; DoBlood(.2, 250); - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 160.); } if (creature == wolftype) { @@ -2448,7 +2457,7 @@ void Person::DoAnimations() camerashake += .4; victim->spurt = 1; DoBlood(.2, 250); - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 160.); } if (creature == wolftype) { @@ -2539,7 +2548,7 @@ void Person::DoAnimations() escapednum = 0; if (id == 0) camerashake += .4; - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(heavyimpactsound, coords, 128.); } XYZ relative; @@ -2564,7 +2573,7 @@ void Person::DoAnimations() escapednum = 0; if (id == 0) camerashake += .4; - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(thudsound, coords); } @@ -2797,7 +2806,7 @@ void Person::DoAnimations() victim->spurt = 1; DoBlood(.2, 235); } - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128); } @@ -2832,15 +2841,15 @@ void Person::DoAnimations() 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); } } @@ -2922,11 +2931,12 @@ void Person::DoAnimations() 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; @@ -2943,11 +2953,12 @@ void Person::DoAnimations() if (aitype != playercontrolled) weaponmissdelay = .6; - if (tutoriallevel != 1) - if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) + if (!Tutorial::active) { + if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) { weapons[weaponids[weaponactive]].bloody = 1; - if (tutoriallevel != 1) + } weapons[weaponids[weaponactive]].blooddrip += 3; + } XYZ footvel, footpoint; footvel = 0; @@ -2956,19 +2967,18 @@ void Person::DoAnimations() } else { footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords; } - if (tutoriallevel != 1) { - if (bloodtoggle) + if (Tutorial::active) { + Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3); + } else { + if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3); + } footvel = DoRotation(facing, 0, 90, 0) * .8; - //footvel.y-=.3; Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); 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) { - Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3); - } victim->DoDamage(damagemult * 0); } } @@ -2977,31 +2987,25 @@ void Person::DoAnimations() 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 victim->DoBloodBig(2 / victim->armorhigh, 185); victim->deathbleeding = 1; emit_sound_at(swordslicesound, victim->coords); - } - //victim->jointVel(abdomen)+=relative*damagemult*200; - if (tutoriallevel != 1) { victim->frameTarget = 0; victim->animTarget = staggerbackhardanim; victim->targetyaw = targetyaw + 180; victim->target = 0; - } - - if (tutoriallevel != 1) { - if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) + if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) { weapons[weaponids[weaponactive]].bloody = 1; + } weapons[weaponids[weaponactive]].blooddrip += 3; float bloodlossamount; bloodlossamount = 200 + abs((float)(Random() % 40)) - 20; victim->bloodloss += bloodlossamount / victim->armorhigh; - //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords)); victim->DoDamage(damagemult * 0); XYZ footvel, footpoint; @@ -3011,8 +3015,9 @@ void Person::DoAnimations() } else { footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords; } - if (bloodtoggle) + if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3); + } footvel = DoRotation(facing, 0, 90, 0) * .8; footvel.y -= .3; Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); @@ -3062,7 +3067,7 @@ void Person::DoAnimations() 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) @@ -3086,7 +3091,7 @@ void Person::DoAnimations() 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); @@ -3096,7 +3101,7 @@ void Person::DoAnimations() 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) @@ -3118,7 +3123,7 @@ void Person::DoAnimations() 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); @@ -3129,7 +3134,7 @@ void Person::DoAnimations() 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) @@ -3166,7 +3171,7 @@ void Person::DoAnimations() } } victim->Puff(abdomen); - if (tutoriallevel != 1) { + if (!Tutorial::active) { victim->DoDamage(damagemult * 100 / victim->protectionhigh); if (!victim->dead) { @@ -3198,7 +3203,7 @@ void Person::DoAnimations() 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); @@ -3221,7 +3226,7 @@ void Person::DoAnimations() 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); @@ -3243,7 +3248,7 @@ void Person::DoAnimations() escapednum = 0; if (id == 0) camerashake += .2; - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(landsound2, victim->coords, 128.); } XYZ relative; @@ -3282,7 +3287,7 @@ void Person::DoAnimations() 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); @@ -3303,7 +3308,7 @@ void Person::DoAnimations() victim->spurt = 1; DoBlood(.2, 230); } - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } if (creature == wolftype) { @@ -3372,7 +3377,7 @@ void Person::DoAnimations() award_bonus(id, staffreversebonus); - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } victim->RagDoll(0); @@ -3471,7 +3476,7 @@ void Person::DoAnimations() victim->spurt = 1; DoBlood(.2, 230); } - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } victim->RagDoll(0); @@ -3664,7 +3669,7 @@ void Person::DoAnimations() DoBlood(.2, 240); } if (weaponactive == -1) { - if (tutoriallevel != 1) { + if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } } @@ -3813,7 +3818,6 @@ void Person::DoAnimations() if (!isnormal(coords.x)) coords = oldcoords; oldcoords = coords; - collided = 0; targetoffset = 0; currentoffset = 0; grabdelay = 1; @@ -4251,15 +4255,15 @@ void Person::DoAnimations() oldframeCurrent = frameCurrent; for (unsigned i = 0; i < skeleton.joints.size(); i++) { - skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier; - skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target); + skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier; + skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target; } offset = currentoffset * (1 - target) + targetoffset * target; for (unsigned i = 0; i < skeleton.muscles.size(); i++) { if (skeleton.muscles[i].visible) { - skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target); - skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target); - skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target); + skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target; + skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target; + skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target; } } } @@ -4286,9 +4290,6 @@ void Person::DoStuff() static XYZ flatfacing; static XYZ flatvelocity; static float flatvelspeed; - static int i, l; - static XYZ average; - static int howmany; static int bloodsize; static int startx, starty, endx, endy; static GLubyte color; @@ -4380,14 +4381,14 @@ void Person::DoStuff() vel[2] = velocity.z; if (id == 0) { - OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel); + OPENAL_3D_SetAttributes(channels[whooshsound], gLoc); OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5); } } } while (flamedelay < 0 && onfire) { flamedelay += .006; - howmany = fabs(Random() % (skeleton.joints.size())); + int howmany = fabs(Random() % (skeleton.joints.size())); if (skeleton.free) { flatvelocity = skeleton.joints[howmany].velocity * scale / 2; flatfacing = skeleton.joints[howmany].position * scale + coords; @@ -4398,9 +4399,9 @@ void Person::DoStuff() 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; - howmany = fabs(Random() % (skeleton.joints.size())); + int howmany = fabs(Random() % (skeleton.joints.size())); if (skeleton.free) { flatvelocity = skeleton.joints[howmany].velocity * scale / 2; flatfacing = skeleton.joints[howmany].position * scale + coords; @@ -4538,7 +4539,7 @@ void Person::DoStuff() if (endy < starty) endy = starty; - for (i = startx; i < endx; i++) { + for (int i = startx; i < endx; i++) { for (int j = starty; j < endy; j++) { if (Random() % 2 == 0) { color = Random() % 85 + 170; @@ -4804,8 +4805,9 @@ void Person::DoStuff() } } - if (dead != 1) + if (dead != 1) { unconscioustime = 0; + } if (dead == 1 || howactive == typesleeping) { unconscioustime += multiplier; @@ -4832,16 +4834,15 @@ void Person::DoStuff() headpoint = coords; if (bloodtoggle && !bled) { terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0); - } - if (bloodtoggle && !bled) - for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) { - int j = terrain.patchobjects[whichpatchx][whichpatchz][l]; - XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0); + for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) { + unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l]; + XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0); float size = .8; float opacity = .6; float yaw = 0; - objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw); + Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw); } + } bled = 1; } @@ -4906,13 +4907,12 @@ void Person::DoStuff() damage += 20; } - if (!dead) + if (!dead) { damage -= multiplier * 13; - if (!dead) permanentdamage -= multiplier * 4; - if (isIdle() || isCrouch()) { - if (!dead) + if (isIdle() || isCrouch()) { permanentdamage -= multiplier * 4; + } } if (damage < 0) damage = 0; @@ -5002,18 +5002,19 @@ void Person::DoStuff() award_bonus(id, deepimpact); DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3)); + XYZ average; average = 0; - howmany = 0; - for (unsigned j = 0; j < skeleton.joints.size(); j++) { - average += skeleton.joints[j].position; - howmany++; - } - average /= howmany; - coords += average * scale; - for (unsigned j = 0; j < skeleton.joints.size(); j++) { - skeleton.joints[j].position -= average; + if (!skeleton.joints.empty()) { + for (unsigned j = 0; j < skeleton.joints.size(); j++) { + average += skeleton.joints[j].position; + } + average /= skeleton.joints.size(); + coords += average * scale; + for (unsigned j = 0; j < skeleton.joints.size(); j++) { + skeleton.joints[j].position -= average; + } + average /= multiplier; } - average /= multiplier; velocity = 0; for (unsigned i = 0; i < skeleton.joints.size(); i++) { @@ -5041,16 +5042,15 @@ void Person::DoStuff() DoBlood(1, 255); if (bloodtoggle && !bled) { terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0); - } - if (bloodtoggle && !bled) - for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) { - int j = terrain.patchobjects[whichpatchx][whichpatchz][l]; - XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0); + for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) { + unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l]; + XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0); float size = .2 * 1.2; float opacity = .6; float yaw = 0; - objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw); + Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw); } + } bled = 1; } if (dead == 2 && bloodloss >= damagetolerance) { @@ -5060,16 +5060,15 @@ void Person::DoStuff() DoBlood(1, 255); if (bloodtoggle && !bled) { terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0); - } - if (bloodtoggle && !bled) - for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) { - int j = terrain.patchobjects[whichpatchx][whichpatchz][l]; - XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0); + for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) { + unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l]; + XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0); float size = .8; float opacity = .6; float yaw = 0; - objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw); + Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw); } + } bled = 1; } } @@ -5085,11 +5084,11 @@ void Person::DoStuff() canrecover = 0; if (velocity.y < -30) canrecover = 0; - for (i = 0; i < objects.numobjects; i++) { - if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) { + for (unsigned int i = 0; i < Object::objects.size(); i++) { + if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) { colviewer = startpoint; coltarget = endpoint; - if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1) + if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) canrecover = 0; } } @@ -5277,36 +5276,36 @@ void Person::DoStuff() if (aitype != passivetype || skeleton.free == 1) if (findLengthfast(&velocity) > .1) - for (i = 0; i < objects.numobjects; i++) { - if (objects.type[i] == firetype) - if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) { + for (unsigned int i = 0; i < Object::objects.size(); i++) { + if (Object::objects[i]->type == firetype) + if (distsqflat(&coords, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 12 && distsq(&coords, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 49) { if (onfire) { - if (!objects.onfire[i]) { - emit_sound_at(firestartsound, objects.position[i]); + if (!Object::objects[i]->onfire) { + emit_sound_at(firestartsound, Object::objects[i]->position); } - objects.onfire[i] = 1; + Object::objects[i]->onfire = 1; } if (!onfire) { - if (objects.onfire[i]) { + if (Object::objects[i]->onfire) { CatchFire(); } } } - if (objects.type[i] == bushtype) - if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) { + if (Object::objects[i]->type == bushtype) + if (distsqflat(&coords, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 12 && distsq(&coords, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 49) { if (onfire) { - if (!objects.onfire[i]) { - emit_sound_at(firestartsound, objects.position[i]); + if (!Object::objects[i]->onfire) { + emit_sound_at(firestartsound, Object::objects[i]->position); } - objects.onfire[i] = 1; + Object::objects[i]->onfire = 1; } if (!onfire) { - if (objects.onfire[i]) { + if (Object::objects[i]->onfire) { CatchFire(); } } - if (objects.messedwith[i] <= 0) { + if (Object::objects[i]->messedwith <= 0) { XYZ tempvel; XYZ pos; @@ -5316,7 +5315,7 @@ void Person::DoStuff() addEnvSound(coords, 4 * findLength(&velocity)); } - int howmany; + int howmany = 0; if (environment == grassyenvironment) howmany = findLength(&velocity) * 4; if (environment == snowyenvironment) @@ -5351,22 +5350,22 @@ void Person::DoStuff() Sprite::setLastSpriteSpecial(2); } } - objects.rotx[i] += velocity.x * multiplier * 6; - objects.roty[i] += velocity.z * multiplier * 6; - objects.messedwith[i] = .5; + Object::objects[i]->rotx += velocity.x * multiplier * 6; + Object::objects[i]->roty += velocity.z * multiplier * 6; + Object::objects[i]->messedwith = .5; } XYZ tempcoord; - if (objects.type[i] == treeleavestype && environment != desertenvironment) { - if (objects.pitch[i] == 0) + if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) { + if (Object::objects[i]->pitch == 0) tempcoord = coords; else { - tempcoord = coords - objects.position[i]; - tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0); - tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0); - tempcoord += objects.position[i]; + tempcoord = coords - Object::objects[i]->position; + tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0); + tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0); + tempcoord += Object::objects[i]->position; } - if (distsqflat(&tempcoord, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 8 && distsq(&tempcoord, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 300 && tempcoord.y > objects.position[i].y + 3 * objects.scale[i]) { - if (objects.messedwith[i] <= 0) { + if (distsqflat(&tempcoord, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 8 && distsq(&tempcoord, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 300 && tempcoord.y > Object::objects[i]->position.y + 3 * Object::objects[i]->scale) { + if (Object::objects[i]->messedwith <= 0) { XYZ tempvel; XYZ pos; @@ -5376,7 +5375,7 @@ void Person::DoStuff() addEnvSound(coords, 4 * findLength(&velocity)); } - int howmany; + int howmany = 0; if (environment == grassyenvironment) howmany = findLength(&velocity) * 4; if (environment == snowyenvironment) @@ -5413,7 +5412,7 @@ void Person::DoStuff() Sprite::setLastSpriteSpecial(2); } } - objects.messedwith[i] = .5; + Object::objects[i]->messedwith = .5; } } } @@ -5426,12 +5425,12 @@ void Person::DoStuff() 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; - i = abs(Random() % 4); if (speechdelay <= 0) { + unsigned int i = abs(Random() % 4); if (creature == rabbittype) { if (i == 0) whichsound = rabbitchitter; @@ -5547,15 +5546,46 @@ void Person::DoStuff() } } - if (animTarget == spinkickanim || animTarget == staffspinhitreversalanim || animTarget == staffspinhitreversedanim || animTarget == staffhitreversalanim || animTarget == staffhitreversedanim || animTarget == hurtidleanim || animTarget == winduppunchanim || animTarget == swordslashreversalanim || animTarget == swordslashreversedanim || animTarget == knifeslashreversalanim || animTarget == knifeslashreversedanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == knifefollowedanim || animTarget == killanim || animTarget == dropkickanim || animTarget == upunchanim || animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim || animTarget == staffgroundsmashanim || animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == lowkickanim || animTarget == sweepreversedanim || animTarget == rabbitkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversalanim || animTarget == jumpreversedanim) { + if (animTarget == spinkickanim || + animTarget == staffspinhitreversalanim || + animTarget == staffspinhitreversedanim || + animTarget == staffhitreversalanim || + animTarget == staffhitreversedanim || + animTarget == hurtidleanim || + animTarget == winduppunchanim || + animTarget == swordslashreversalanim || + animTarget == swordslashreversedanim || + animTarget == knifeslashreversalanim || + animTarget == knifeslashreversedanim || + animTarget == knifethrowanim || + animTarget == knifefollowanim || + animTarget == knifefollowedanim || + animTarget == killanim || + animTarget == dropkickanim || + animTarget == upunchanim || + animTarget == knifeslashstartanim || + animTarget == swordslashanim || + animTarget == staffhitanim || + animTarget == staffspinhitanim || + animTarget == staffgroundsmashanim || + animTarget == spinkickreversalanim || + animTarget == sweepreversalanim || + animTarget == lowkickanim || + animTarget == sweepreversedanim || + animTarget == rabbitkickreversalanim || + animTarget == rabbitkickreversedanim || + animTarget == jumpreversalanim || + animTarget == jumpreversedanim) { //close hands and yell - if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) { + if (righthandmorphend != 1 && + righthandmorphness == targetrighthandmorphness) { righthandmorphness = 0; righthandmorphend = 1; targetrighthandmorphness = 1; } - if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) { + if (lefthandmorphend != 1 && + lefthandmorphness == targetlefthandmorphness) { lefthandmorphness = 0; lefthandmorphend = 1; targetlefthandmorphness = 1; @@ -5615,7 +5645,8 @@ void Person::DoStuff() ReflectVector(&facing, terrainnormal); Normalise(&facing); - if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) { + if (isRun() || + animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) { if (onterrain) targettilt2 = -facing.y * 20; else @@ -5880,8 +5911,9 @@ void Person::DoStuff() velocity.y = 0; if (velspeed < multiplier * 300 * scale) { velocity = 0; - } else + } else { velocity -= velocity / velspeed * multiplier * 300 * scale; + } if (velspeed > 5 && (isLanding() || isLandhard())) { skiddingdelay += multiplier; if (skiddelay <= 0) { @@ -5889,17 +5921,13 @@ void Person::DoStuff() FootLand(rightfoot, .5); skiddelay = .02; } - } else + } else { skiddingdelay = 0; + } } if (isLandhard()) { velspeed = findLength(&velocity); - velocity.y = 0; - if (velspeed < multiplier * 600 * scale) { - velocity = 0; - } else - velocity -= velocity / velspeed * multiplier * 600 * scale; velocity = 0; if (velspeed > 5 && (isLanding() || isLandhard())) { skiddingdelay += multiplier; @@ -5908,8 +5936,9 @@ void Person::DoStuff() FootLand(rightfoot, .5); skiddelay = .02; } - } else + } else { skiddingdelay = 0; + } } if (skiddingdelay < 0) @@ -6056,7 +6085,7 @@ int Person::DrawSkeleton() } static XYZ mid; static float M[16]; - static int i, k; + static int k; static int weaponattachmuscle; static int weaponrotatemuscle; static XYZ weaponpoint; @@ -6096,19 +6125,19 @@ int Person::DrawSkeleton() if (Animation::animations[animTarget].attack == 3) targetheadyaw += 180; } - for (i = 0; i < skeleton.drawmodel.vertexNum; i++) { + for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) { skeleton.drawmodel.vertex[i] = 0; skeleton.drawmodel.vertex[i].y = 999; } - for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) { + for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) { skeleton.drawmodellow.vertex[i] = 0; skeleton.drawmodellow.vertex[i].y = 999; } - for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) { + for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) { skeleton.drawmodelclothes.vertex[i] = 0; skeleton.drawmodelclothes.vertex[i].y = 999; } - for (unsigned i = 0; i < skeleton.muscles.size(); i++) { + for (unsigned int i = 0; i < skeleton.muscles.size(); i++) { // convenience renames const int p1 = skeleton.muscles[i].parent1->label; const int p2 = skeleton.muscles[i].parent2->label; @@ -6319,19 +6348,20 @@ int Person::DrawSkeleton() glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glBegin(GL_POINTS); - if (playerdetail) - for (i = 0; i < skeleton.drawmodel.vertexNum; i++) { + if (playerdetail) { + for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) { XYZ &v0 = skeleton.drawmodel.vertex[i]; glVertex3f(v0.x, v0.y, v0.z); } + } glEnd(); glBegin(GL_LINES); - if (playerdetail) - for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) { - XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]]; - XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]]; - XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]]; + if (playerdetail) { + for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) { + const XYZ &v0 = skeleton.drawmodel.getTriangleVertex(i, 0); + const XYZ &v1 = skeleton.drawmodel.getTriangleVertex(i, 1); + const XYZ &v2 = skeleton.drawmodel.getTriangleVertex(i, 2); glVertex3f(v0.x, v0.y, v0.z); glVertex3f(v1.x, v1.y, v1.z); glVertex3f(v1.x, v1.y, v1.z); @@ -6339,6 +6369,7 @@ int Person::DrawSkeleton() glVertex3f(v2.x, v2.y, v2.z); glVertex3f(v0.x, v0.y, v0.z); } + } glEnd(); } @@ -6366,7 +6397,7 @@ int Person::DrawSkeleton() 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); @@ -6383,21 +6414,21 @@ int Person::DrawSkeleton() } 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); @@ -6416,14 +6447,14 @@ int Person::DrawSkeleton() 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); @@ -6431,7 +6462,7 @@ int Person::DrawSkeleton() } - if (tutoriallevel && id != 0) { + if (Tutorial::active && id != 0) { glPopMatrix(); glMatrixMode(GL_MODELVIEW); glEnable(GL_TEXTURE_2D); @@ -6450,7 +6481,7 @@ int Person::DrawSkeleton() if (num_weapons > 0) { for (k = 0; k < num_weapons; k++) { - i = weaponids[k]; + int i = weaponids[k]; if (weaponactive == k) { if (weapons[i].getType() != staff) { for (unsigned j = 0; j < skeleton.muscles.size(); j++) { @@ -6688,7 +6719,6 @@ int Person::DrawSkeleton() */ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model) { - static int i, j; static float distance; static float olddistance; static int intersecting; @@ -6706,14 +6736,14 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, return -1; if (*rotate) *p1 = DoRotation(*p1, 0, -*rotate, 0); - for (i = 0; i < 4; i++) { - for (j = 0; j < model->TriangleNum; j++) { - if (model->facenormals[j].y <= slopethreshold) { + for (int i = 0; i < 4; i++) { + for (unsigned int j = 0; j < model->Triangles.size(); j++) { + if (model->Triangles[j].facenormal.y <= slopethreshold) { intersecting = 0; - distance = abs((model->facenormals[j].x * p1->x) + (model->facenormals[j].y * p1->y) + (model->facenormals[j].z * p1->z) - ((model->facenormals[j].x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->facenormals[j].y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->facenormals[j].z * model->vertex[model->Triangles[j].vertex[0]].z))); + distance = abs((model->Triangles[j].facenormal.x * p1->x) + (model->Triangles[j].facenormal.y * p1->y) + (model->Triangles[j].facenormal.z * p1->z) - ((model->Triangles[j].facenormal.x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->Triangles[j].facenormal.y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->Triangles[j].facenormal.z * model->vertex[model->Triangles[j].vertex[0]].z))); if (distance < radius) { - point = *p1 - model->facenormals[j] * distance; - if (PointInTriangle( &point, model->facenormals[j], &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]])) + point = *p1 - model->Triangles[j].facenormal * distance; + if (PointInTriangle( &point, model->Triangles[j].facenormal, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]])) intersecting = 1; if (!intersecting) intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]], @@ -6728,11 +6758,11 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, &model->vertex[model->Triangles[j].vertex[2]], p1, &radius); end = *p1 - point; - if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) { + if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) { start = *p1; end = *p1; end.y -= radius; - if (LineFacetd(&start, &end, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]], &model->facenormals[j], &point)) { + if (LineFacetd(&start, &end, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]], &model->Triangles[j].facenormal, &point)) { p1->y = point.y + radius; if ((animTarget == jumpdownanim || isFlip())) { if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) @@ -6772,23 +6802,23 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, } } } - for (j = 0; j < model->TriangleNum; j++) { - if (model->facenormals[j].y > slopethreshold) { + for (unsigned int j = 0; j < model->Triangles.size(); j++) { + if (model->Triangles[j].facenormal.y > slopethreshold) { intersecting = 0; start = *p1; start.y -= radius / 4; XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]]; XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]]; XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]]; - distance = abs((model->facenormals[j].x * start.x) - + (model->facenormals[j].y * start.y) - + (model->facenormals[j].z * start.z) - - ((model->facenormals[j].x * v0.x) - + (model->facenormals[j].y * v0.y) - + (model->facenormals[j].z * v0.z))); + distance = abs((model->Triangles[j].facenormal.x * start.x) + + (model->Triangles[j].facenormal.y * start.y) + + (model->Triangles[j].facenormal.z * start.z) + - ((model->Triangles[j].facenormal.x * v0.x) + + (model->Triangles[j].facenormal.y * v0.y) + + (model->Triangles[j].facenormal.z * v0.z))); if (distance < radius * .5) { - point = start - model->facenormals[j] * distance; - if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2)) + point = start - model->Triangles[j].facenormal * distance; + if (PointInTriangle( &point, model->Triangles[j].facenormal, &v0, &v1, &v2)) intersecting = 1; if (!intersecting) intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2); @@ -6797,14 +6827,14 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, if (!intersecting) intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2); end = *p1 - point; - if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) { + if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) { if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) { start = velocity; - velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier; + velocity -= DoRotation(model->Triangles[j].facenormal, 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->Triangles[j].facenormal, 0, *rotate, 0))); //(distance-radius*.5)/multiplier; if (findLengthfast(&start) < findLengthfast(&velocity)) velocity = start; } - *p1 += model->facenormals[j] * (distance - radius * .5); + *p1 += model->Triangles[j].facenormal * (distance - radius * .5); } } if ((distance < olddistance || firstintersecting == -1) && intersecting) { @@ -6824,6 +6854,51 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, return firstintersecting; } +int findPathDist(int start, int end) +{ + int connected; + int closest; + + unsigned int smallestcount = 1000; + for (char i = 0; i < 50; i++) { + unsigned int count = 0; + int last = start; + int last2 = -1; + int last3 = -1; + int last4 = -1; + while (last != end && count < 30) { + closest = -1; + for (int j = 0; j < Game::numpathpoints; j++) { + if (j != last && j != last2 && j != last3 && j != last4) { + connected = 0; + if (Game::numpathpointconnect[j]) + for (int k = 0; k < Game::numpathpointconnect[j]; k++) { + if (Game::pathpointconnect[j][k] == last)connected = 1; + } + if (!connected) + if (Game::numpathpointconnect[last]) + for (int k = 0; k < Game::numpathpointconnect[last]; k++) { + if (Game::pathpointconnect[last][k] == j)connected = 1; + } + if (connected) + if (closest == -1 || Random() % 2 == 0) { + closest = j; + } + } + } + last4 = last3; + last3 = last2; + last2 = last; + last = closest; + count++; + } + if (count < smallestcount) { + smallestcount = count; + } + } + return smallestcount; +} + void Person::takeWeapon(int weaponId) { weaponactive = 0; @@ -6896,3 +6971,985 @@ bool Person::addClothes(const int& clothesId) return 0; } } + +void Person::doAI() +{ + if (aitype != playercontrolled && !Dialog::inDialog()) { + jumpclimb = 0; + //disable movement in editor + if (Game::editorenabled) + stunned = 1; + + pause = 0; + if (distsqflat(&Person::players[0]->coords, &coords) < 30 && + Person::players[0]->coords.y > coords.y + 2 && + !Person::players[0]->onterrain) + pause = 1; + + //pathfinding + if (aitype == pathfindtype) { + if (finalpathfindpoint == -1) { + float closestdistance; + float tempdist; + int closest; + XYZ colpoint; + closest = -1; + closestdistance = -1; + for (int j = 0; j < Game::numpathpoints; j++) { + if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) { + closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]); + closest = j; + finaltarget = Game::pathpoint[j]; + } + } + finalpathfindpoint = closest; + for (int j = 0; j < Game::numpathpoints; j++) { + for (int k = 0; k < Game::numpathpointconnect[j]; k++) { + DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint); + if (sq(tempdist) < closestdistance) + if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) < + findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) { + closestdistance = sq(tempdist); + closest = j; + finaltarget = colpoint; + } + } + } + finalpathfindpoint = closest; + + } + if (targetpathfindpoint == -1) { + float closestdistance; + float tempdist; + int closest; + XYZ colpoint; + closest = -1; + closestdistance = -1; + if (lastpathfindpoint == -1) { + for (int j = 0; j < Game::numpathpoints; j++) { + if (j != lastpathfindpoint) + if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) { + closestdistance = distsq(&coords, &Game::pathpoint[j]); + closest = j; + } + } + targetpathfindpoint = closest; + for (int j = 0; j < Game::numpathpoints; j++) + if (j != lastpathfindpoint) + for (int k = 0; k < Game::numpathpointconnect[j]; k++) { + DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint ); + if (sq(tempdist) < closestdistance) { + if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) < + findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) { + closestdistance = sq(tempdist); + closest = j; + } + } + } + targetpathfindpoint = closest; + } else { + for (int j = 0; j < Game::numpathpoints; j++) + if (j != lastpathfindpoint && + j != lastpathfindpoint2 && + j != lastpathfindpoint3 && + j != lastpathfindpoint4) { + bool connected = 0; + if (Game::numpathpointconnect[j]) + for (int k = 0; k < Game::numpathpointconnect[j]; k++) + if (Game::pathpointconnect[j][k] == lastpathfindpoint) + connected = 1; + if (!connected) + if (Game::numpathpointconnect[lastpathfindpoint]) + for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) + if (Game::pathpointconnect[lastpathfindpoint][k] == j) + connected = 1; + if (connected) { + tempdist = findPathDist(j, finalpathfindpoint); + if (closest == -1 || tempdist < closestdistance) { + closestdistance = tempdist; + closest = j; + } + } + } + targetpathfindpoint = closest; + } + } + losupdatedelay -= multiplier; + + targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]); + lookyaw = targetyaw; + + //reached target point + if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) { + lastpathfindpoint4 = lastpathfindpoint3; + lastpathfindpoint3 = lastpathfindpoint2; + lastpathfindpoint2 = lastpathfindpoint; + lastpathfindpoint = targetpathfindpoint; + if (lastpathfindpoint2 == -1) + lastpathfindpoint2 = lastpathfindpoint; + if (lastpathfindpoint3 == -1) + lastpathfindpoint3 = lastpathfindpoint2; + if (lastpathfindpoint4 == -1) + lastpathfindpoint4 = lastpathfindpoint3; + targetpathfindpoint = -1; + } + if ( distsqflat(&coords, &finalfinaltarget) < + distsqflat(&coords, &finaltarget) || + distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) || + lastpathfindpoint == finalpathfindpoint) { + aitype = passivetype; + } + + forwardkeydown = 1; + leftkeydown = 0; + backkeydown = 0; + rightkeydown = 0; + crouchkeydown = 0; + attackkeydown = 0; + throwkeydown = 0; + + if (avoidcollided > .8 && !jumpkeydown && collided < .8) + targetyaw += 90 * (whichdirection * 2 - 1); + + if (collided < 1 || animTarget != jumpupanim) + jumpkeydown = 0; + if ((collided > .8 && jumppower >= 5)) + jumpkeydown = 1; + + if ((!Tutorial::active || cananger) && + hostile && + !Person::players[0]->dead && + distsq(&coords, &Person::players[0]->coords) < 400 && + occluded < 25) { + if (distsq(&coords, &Person::players[0]->coords) < 12 && + Animation::animations[Person::players[0]->animTarget].height != lowheight && + !Game::editorenabled && + (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) + aitype = attacktypecutoff; + if (distsq(&coords, &Person::players[0]->coords) < 30 && + Animation::animations[Person::players[0]->animTarget].height == highheight && + !Game::editorenabled) + aitype = attacktypecutoff; + + if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) { + losupdatedelay = .2; + for (unsigned j = 0; j < Person::players.size(); j++) + if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) + if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) + if (distsq(&coords, &Person::players[j]->coords) < 400) + if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) + if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) + if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide( + DoRotation(jointPos(head), 0, yaw, 0) + *scale + coords, + DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) + *Person::players[j]->scale + Person::players[j]->coords) || + (Person::players[j]->animTarget == hanganim && + normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) { + aitype = searchtype; + lastchecktime = 12; + lastseen = Person::players[j]->coords; + lastseentime = 12; + } + } + } + if (aitype == attacktypecutoff && Game::musictype != 2) + if (creature != wolftype) { + stunned = .6; + surprised = .6; + } + } + + if (aitype != passivetype && Game::leveltime > .5) + howactive = typeactive; + + if (aitype == passivetype) { + aiupdatedelay -= multiplier; + losupdatedelay -= multiplier; + lastseentime += multiplier; + pausetime -= multiplier; + if (lastseentime > 1) + lastseentime = 1; + + if (aiupdatedelay < 0) { + if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) { + targetyaw = roughDirectionTo(coords, waypoints[waypoint]); + lookyaw = targetyaw; + aiupdatedelay = .05; + + if (distsqflat(&coords, &waypoints[waypoint]) < 1) { + if (waypointtype[waypoint] == wppause) + pausetime = 4; + waypoint++; + if (waypoint > numwaypoints - 1) + waypoint = 0; + + } + } + + if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) + forwardkeydown = 1; + else + forwardkeydown = 0; + leftkeydown = 0; + backkeydown = 0; + rightkeydown = 0; + crouchkeydown = 0; + attackkeydown = 0; + throwkeydown = 0; + + if (avoidcollided > .8 && !jumpkeydown && collided < .8) { + if (!avoidsomething) + targetyaw += 90 * (whichdirection * 2 - 1); + else { + XYZ leftpos, rightpos; + float leftdist, rightdist; + leftpos = coords + DoRotation(facing, 0, 90, 0); + rightpos = coords - DoRotation(facing, 0, 90, 0); + leftdist = distsq(&leftpos, &avoidwhere); + rightdist = distsq(&rightpos, &avoidwhere); + if (leftdist < rightdist) + targetyaw += 90; + else + targetyaw -= 90; + } + } + } + if (collided < 1 || animTarget != jumpupanim) + jumpkeydown = 0; + if ((collided > .8 && jumppower >= 5)) + jumpkeydown = 1; + + + //hearing sounds + if (!Game::editorenabled) { + if (howactive <= typesleeping) + if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) + for (int j = 0; j < numenvsounds; j++) { + float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j]; + if (vol > 0 && distsq(&coords, &envsound[j]) < + 2 * (vol + vol * (creature == rabbittype) * 3)) + aitype = attacktypecutoff; + } + + if (aitype != passivetype) { + if (howactive == typesleeping) + setTargetAnimation(getupfromfrontanim); + howactive = typeactive; + } + } + + if (howactive < typesleeping && + ((!Tutorial::active || cananger) && hostile) && + !Person::players[0]->dead && + distsq(&coords, &Person::players[0]->coords) < 400 && + occluded < 25) { + if (distsq(&coords, &Person::players[0]->coords) < 12 && + Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) + aitype = attacktypecutoff; + if (distsq(&coords, &Person::players[0]->coords) < 30 && + Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) + aitype = attacktypecutoff; + + //wolf smell + if (creature == wolftype) { + XYZ windsmell; + for (unsigned j = 0; j < Person::players.size(); j++) { + if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) { + float smelldistance = 50; + if (j == 0 && Person::players[j]->num_weapons > 0) { + if (weapons[Person::players[j]->weaponids[0]].bloody) + smelldistance = 100; + if (Person::players[j]->num_weapons == 2) + if (weapons[Person::players[j]->weaponids[1]].bloody) + smelldistance = 100; + } + if (j != 0) + smelldistance = 100; + windsmell = windvector; + Normalise(&windsmell); + windsmell = windsmell * 2 + Person::players[j]->coords; + if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) + aitype = attacktypecutoff; + } + } + } + + if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) { + losupdatedelay = .2; + for (unsigned j = 0; j < Person::players.size(); j++) { + if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) { + if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) + if (distsq(&coords, &Person::players[j]->coords) < 400) + if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) + if ((-1 == Object::checkcollide( + DoRotation(jointPos(head), 0, yaw, 0)* + scale + coords, + DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)* + Person::players[j]->scale + Person::players[j]->coords) && + !Person::players[j]->isWallJump()) || + (Person::players[j]->animTarget == hanganim && + normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) { + lastseentime -= .2; + if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) + lastseentime -= .4; + else + lastseentime -= .6; + } + if (lastseentime <= 0) { + aitype = searchtype; + lastchecktime = 12; + lastseen = Person::players[j]->coords; + lastseentime = 12; + } + } + } + } + } + //alerted surprise + if (aitype == attacktypecutoff && Game::musictype != 2) { + if (creature != wolftype) { + stunned = .6; + surprised = .6; + } + if (creature == wolftype) { + stunned = .47; + surprised = .47; + } + numseen++; + } + } + + //search for player + int j; + if (aitype == searchtype) { + aiupdatedelay -= multiplier; + losupdatedelay -= multiplier; + if (!pause) + lastseentime -= multiplier; + lastchecktime -= multiplier; + + if (isRun() && !onground) { + if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) { + XYZ test2 = coords + facing; + test2.y += 5; + XYZ test = coords + facing; + test.y -= 10; + j = Object::checkcollide(test2, test, laststanding); + if (j == -1) + j = Object::checkcollide(test2, test); + if (j == -1) { + velocity = 0; + setTargetAnimation(getStop()); + targetyaw += 180; + stunned = .5; + //aitype=passivetype; + aitype = pathfindtype; + finalfinaltarget = waypoints[waypoint]; + finalpathfindpoint = -1; + targetpathfindpoint = -1; + lastpathfindpoint = -1; + lastpathfindpoint2 = -1; + lastpathfindpoint3 = -1; + lastpathfindpoint4 = -1; + } else + laststanding = j; + } + } + //check out last seen location + if (aiupdatedelay < 0) { + targetyaw = roughDirectionTo(coords, lastseen); + lookyaw = targetyaw; + aiupdatedelay = .05; + forwardkeydown = 1; + + if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) { + forwardkeydown = 0; + aiupdatedelay = 1; + lastseen.x += (float(Random() % 100) - 50) / 25; + lastseen.z += (float(Random() % 100) - 50) / 25; + lastchecktime = 3; + } + + leftkeydown = 0; + backkeydown = 0; + rightkeydown = 0; + crouchkeydown = 0; + attackkeydown = 0; + throwkeydown = 0; + + if (avoidcollided > .8 && !jumpkeydown && collided < .8) { + if (!avoidsomething) + targetyaw += 90 * (whichdirection * 2 - 1); + else { + XYZ leftpos, rightpos; + float leftdist, rightdist; + leftpos = coords + DoRotation(facing, 0, 90, 0); + rightpos = coords - DoRotation(facing, 0, 90, 0); + leftdist = distsq(&leftpos, &avoidwhere); + rightdist = distsq(&rightpos, &avoidwhere); + if (leftdist < rightdist) + targetyaw += 90; + else + targetyaw -= 90; + } + } + } + if (collided < 1 || animTarget != jumpupanim) + jumpkeydown = 0; + if ((collided > .8 && jumppower >= 5)) + jumpkeydown = 1; + + if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) + for (int k = 0; k < numenvsounds; k++) { + if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) { + aitype = attacktypecutoff; + } + } + + if (!Person::players[0]->dead && + losupdatedelay < 0 && + !Game::editorenabled && + occluded < 2 && + ((!Tutorial::active || cananger) && hostile)) { + losupdatedelay = .2; + if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) { + aitype = attacktypecutoff; + lastseentime = 1; + } + if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) + //TODO: factor out canSeePlayer() + if (distsq(&coords, &Person::players[0]->coords) < 400) + if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) + if ((Object::checkcollide( + DoRotation(jointPos(head), 0, yaw, 0)* + scale + coords, + DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)* + Person::players[0]->scale + Person::players[0]->coords) == -1) || + (Person::players[0]->animTarget == hanganim && normaldotproduct( + Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) { + /* //TODO: changed j to 0 on a whim, make sure this is correct + (Person::players[j]->animTarget==hanganim&&normaldotproduct( + Person::players[j]->facing,coords-Person::players[j]->coords)<0) + */ + aitype = attacktypecutoff; + lastseentime = 1; + } + } + //player escaped + if (lastseentime < 0) { + //aitype=passivetype; + numescaped++; + aitype = pathfindtype; + finalfinaltarget = waypoints[waypoint]; + finalpathfindpoint = -1; + targetpathfindpoint = -1; + lastpathfindpoint = -1; + lastpathfindpoint2 = -1; + lastpathfindpoint3 = -1; + lastpathfindpoint4 = -1; + } + } + + if (aitype != gethelptype) + runninghowlong = 0; + + //get help from buddies + if (aitype == gethelptype) { + runninghowlong += multiplier; + aiupdatedelay -= multiplier; + + if (aiupdatedelay < 0 || ally == 0) { + aiupdatedelay = .2; + + //find closest ally + //TODO: factor out closest search somehow + if (!ally) { + int closest = -1; + float closestdist = -1; + for (unsigned k = 0; k < Person::players.size(); k++) { + if ((k != id) && (k != 0) && !Person::players[k]->dead && + (Person::players[k]->howactive < typedead1) && + !Person::players[k]->skeleton.free && + (Person::players[k]->aitype == passivetype)) { + float distance = distsq(&coords, &Person::players[k]->coords); + if (closestdist == -1 || distance < closestdist) { + closestdist = distance; + closest = k; + } + closest = k; + } + } + if (closest != -1) { + ally = closest; + } else { + ally = 0; + } + lastseen = Person::players[0]->coords; + lastseentime = 12; + } + + + lastchecktime = 12; + + XYZ facing = coords; + XYZ flatfacing = Person::players[ally]->coords; + facing.y += jointPos(head).y * scale; + flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale; + if (-1 != Object::checkcollide(facing, flatfacing)) + lastseentime -= .1; + + //no available ally, run back to player + if (ally <= 0 || + Person::players[ally]->skeleton.free || + Person::players[ally]->aitype != passivetype || + lastseentime <= 0) { + aitype = searchtype; + lastseentime = 12; + } + + //seek out ally + if (ally > 0) { + targetyaw = roughDirectionTo(coords, Person::players[ally]->coords); + lookyaw = targetyaw; + aiupdatedelay = .05; + forwardkeydown = 1; + + if (distsqflat(&coords, &Person::players[ally]->coords) < 3) { + aitype = searchtype; + lastseentime = 12; + Person::players[ally]->aitype = searchtype; + if (Person::players[ally]->lastseentime < lastseentime) { + Person::players[ally]->lastseen = lastseen; + Person::players[ally]->lastseentime = lastseentime; + Person::players[ally]->lastchecktime = lastchecktime; + } + } + + if (avoidcollided > .8 && !jumpkeydown && collided < .8) { + if (!avoidsomething) + targetyaw += 90 * (whichdirection * 2 - 1); + else { + XYZ leftpos, rightpos; + float leftdist, rightdist; + leftpos = coords + DoRotation(facing, 0, 90, 0); + rightpos = coords - DoRotation(facing, 0, 90, 0); + leftdist = distsq(&leftpos, &avoidwhere); + rightdist = distsq(&rightpos, &avoidwhere); + if (leftdist < rightdist) + targetyaw += 90; + else + targetyaw -= 90; + } + } + } + + leftkeydown = 0; + backkeydown = 0; + rightkeydown = 0; + crouchkeydown = 0; + attackkeydown = 0; + } + if (collided < 1 || animTarget != jumpupanim) + jumpkeydown = 0; + if (collided > .8 && jumppower >= 5) + jumpkeydown = 1; + } + + //retreiving a weapon on the ground + if (aitype == getweapontype) { + aiupdatedelay -= multiplier; + lastchecktime -= multiplier; + + if (aiupdatedelay < 0) { + aiupdatedelay = .2; + + //ALLY IS WEPON + if (ally < 0) { + int closest = -1; + float closestdist = -1; + for (unsigned k = 0; k < weapons.size(); k++) + if (weapons[k].owner == -1) { + float distance = distsq(&coords, &weapons[k].position); + if (closestdist == -1 || distance < closestdist) { + closestdist = distance; + closest = k; + } + closest = k; + } + if (closest != -1) + ally = closest; + else + ally = -1; + } + + lastseentime = 12; + + if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) + if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) { + aitype = attacktypecutoff; + lastseentime = 1; + } + if (!Person::players[0]->dead) + if (ally >= 0) { + if (weapons[ally].owner != -1 || + distsq(&coords, &weapons[ally].position) > 16) { + aitype = attacktypecutoff; + lastseentime = 1; + } + //TODO: factor these out as moveToward() + targetyaw = roughDirectionTo(coords, weapons[ally].position); + lookyaw = targetyaw; + aiupdatedelay = .05; + forwardkeydown = 1; + + + if (avoidcollided > .8 && !jumpkeydown && collided < .8) { + if (!avoidsomething) + targetyaw += 90 * (whichdirection * 2 - 1); + else { + XYZ leftpos, rightpos; + float leftdist, rightdist; + leftpos = coords + DoRotation(facing, 0, 90, 0); + rightpos = coords - DoRotation(facing, 0, 90, 0); + leftdist = distsq(&leftpos, &avoidwhere); + rightdist = distsq(&rightpos, &avoidwhere); + if (leftdist < rightdist) + targetyaw += 90; + else + targetyaw -= 90; + } + } + } + + leftkeydown = 0; + backkeydown = 0; + rightkeydown = 0; + attackkeydown = 0; + throwkeydown = 1; + crouchkeydown = 0; + if (animTarget != crouchremoveknifeanim && + animTarget != removeknifeanim) + throwtogglekeydown = 0; + drawkeydown = 0; + } + if (collided < 1 || animTarget != jumpupanim) + jumpkeydown = 0; + if ((collided > .8 && jumppower >= 5)) + jumpkeydown = 1; + } + + if (aitype == attacktypecutoff) { + aiupdatedelay -= multiplier; + //dodge or reverse rabbit kicks, knife throws, flips + if (damage < damagetolerance * 2 / 3) + if ((Person::players[0]->animTarget == rabbitkickanim || + Person::players[0]->animTarget == knifethrowanim || + (Person::players[0]->isFlip() && + normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) && + !Person::players[0]->skeleton.free && + (aiupdatedelay < .1)) { + attackkeydown = 0; + if (isIdle()) + crouchkeydown = 1; + if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) { + if (weapons[Person::players[0]->weaponids[0]].getType() == knife) { + if (isIdle() || isCrouch() || isRun() || isFlip()) { + if (abs(Random() % 2) == 0) { + setTargetAnimation(backhandspringanim); + } else { + setTargetAnimation(rollanim); + } + targetyaw += 90 * (abs(Random() % 2) * 2 - 1); + wentforweapon = 0; + } + if (animTarget == jumpupanim || animTarget == jumpdownanim) { + setTargetAnimation(flipanim); + } + } + } + forwardkeydown = 0; + aiupdatedelay = .02; + } + //get confused by flips + if (Person::players[0]->isFlip() && + !Person::players[0]->skeleton.free && + Person::players[0]->animTarget != walljumprightkickanim && + Person::players[0]->animTarget != walljumpleftkickanim) { + if (distsq(&Person::players[0]->coords, &coords) < 25) + if ((1 - damage / damagetolerance) > .5) + stunned = 1; + } + //go for weapon on the ground + if (wentforweapon < 3) + for (unsigned k = 0; k < weapons.size(); k++) + if (creature != wolftype) + if (num_weapons == 0 && + weapons[k].owner == -1 && + weapons[k].velocity.x == 0 && + weapons[k].velocity.z == 0 && + weapons[k].velocity.y == 0) { + if (distsq(&coords, &weapons[k].position) < 16) { + wentforweapon++; + lastchecktime = 6; + aitype = getweapontype; + ally = -1; + } + } + //dodge/reverse walljump kicks + if (damage < damagetolerance / 2) + if (Animation::animations[animTarget].height != highheight) + if (damage < damagetolerance * .5 && + ((Person::players[0]->animTarget == walljumprightkickanim || + Person::players[0]->animTarget == walljumpleftkickanim) && + ((aiupdatedelay < .15 && + difficulty == 2) || + (aiupdatedelay < .08 && + difficulty != 2)))) { + crouchkeydown = 1; + } + //walked off a ledge (?) + if (isRun() && !onground) + if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) { + XYZ test2 = coords + facing; + test2.y += 5; + XYZ test = coords + facing; + test.y -= 10; + j = Object::checkcollide(test2, test, laststanding); + if (j == -1) + j = Object::checkcollide(test2, test); + if (j == -1) { + velocity = 0; + setTargetAnimation(getStop()); + targetyaw += 180; + stunned = .5; + aitype = pathfindtype; + finalfinaltarget = waypoints[waypoint]; + finalpathfindpoint = -1; + targetpathfindpoint = -1; + lastpathfindpoint = -1; + lastpathfindpoint2 = -1; + lastpathfindpoint3 = -1; + lastpathfindpoint4 = -1; + } else + laststanding = j; + } + //lose sight of player in the air (?) + if (Person::players[0]->coords.y > coords.y + 5 && + Animation::animations[Person::players[0]->animTarget].height != highheight && + !Person::players[0]->onterrain) { + aitype = pathfindtype; + finalfinaltarget = waypoints[waypoint]; + finalpathfindpoint = -1; + targetpathfindpoint = -1; + lastpathfindpoint = -1; + lastpathfindpoint2 = -1; + lastpathfindpoint3 = -1; + lastpathfindpoint4 = -1; + } + //it's time to think (?) + if (aiupdatedelay < 0 && + !Animation::animations[animTarget].attack && + animTarget != staggerbackhighanim && + animTarget != staggerbackhardanim && + animTarget != backhandspringanim && + animTarget != dodgebackanim) { + //draw weapon + if (weaponactive == -1 && num_weapons > 0) + drawkeydown = Random() % 2; + else + drawkeydown = 0; + rabbitkickenabled = Random() % 2; + //chase player + XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity; + XYZ targetpoint = Person::players[0]->coords; + if (distsq(&Person::players[0]->coords, &coords) < + distsq(&rotatetarget, &coords)) + targetpoint += Person::players[0]->velocity * + findDistance(&Person::players[0]->coords, &coords) / findLength(&velocity); + targetyaw = roughDirectionTo(coords, targetpoint); + lookyaw = targetyaw; + aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000); + + if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) + forwardkeydown = 1; + else if ((distsq(&coords, &Person::players[0]->coords) > 16 || + distsq(&coords, &Person::players[0]->coords) < 9) && + Person::players[0]->weaponactive != -1) + forwardkeydown = 1; + else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) + forwardkeydown = 1; + else + forwardkeydown = 0; + //chill out around the corpse + if (Person::players[0]->dead) { + forwardkeydown = 0; + if (Random() % 10 == 0) + forwardkeydown = 1; + if (Random() % 100 == 0) { + aitype = pathfindtype; + finalfinaltarget = waypoints[waypoint]; + finalpathfindpoint = -1; + targetpathfindpoint = -1; + lastpathfindpoint = -1; + lastpathfindpoint2 = -1; + lastpathfindpoint3 = -1; + lastpathfindpoint4 = -1; + } + } + leftkeydown = 0; + backkeydown = 0; + rightkeydown = 0; + crouchkeydown = 0; + throwkeydown = 0; + + if (avoidcollided > .8 && !jumpkeydown && collided < .8) + targetyaw += 90 * (whichdirection * 2 - 1); + //attack!!! + if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) + attackkeydown = 1; + else + attackkeydown = 0; + if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) + attackkeydown = 0; + + //TODO: wat + if (aitype != playercontrolled && + (isIdle() || + isCrouch() || + isRun())) { + int target = -2; + for (unsigned j = 0; j < Person::players.size(); j++) + if (j != id && !Person::players[j]->skeleton.free && + Person::players[j]->hasvictim && + (Tutorial::active && reversaltrain || + Random() % 2 == 0 && difficulty == 2 || + Random() % 4 == 0 && difficulty == 1 || + Random() % 8 == 0 && difficulty == 0 || + Person::players[j]->lastattack2 == Person::players[j]->animTarget && + Person::players[j]->lastattack3 == Person::players[j]->animTarget && + (Random() % 2 == 0 || difficulty == 2) || + (isIdle() || isRun()) && + Person::players[j]->weaponactive != -1 || + Person::players[j]->animTarget == swordslashanim && + weaponactive != -1 || + Person::players[j]->animTarget == staffhitanim || + Person::players[j]->animTarget == staffspinhitanim)) + if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 && + Person::players[j]->victim == Person::players[id] && + (Person::players[j]->animTarget == sweepanim || + Person::players[j]->animTarget == spinkickanim || + Person::players[j]->animTarget == staffhitanim || + Person::players[j]->animTarget == staffspinhitanim || + Person::players[j]->animTarget == winduppunchanim || + Person::players[j]->animTarget == upunchanim || + Person::players[j]->animTarget == wolfslapanim || + Person::players[j]->animTarget == knifeslashstartanim || + Person::players[j]->animTarget == swordslashanim && + (distsq(&Person::players[j]->coords, &coords) < 2 || + weaponactive != -1))) { + if (target >= 0) { + target = -1; + } else { + target = j; + } + } + if (target >= 0) + Person::players[target]->Reverse(); + } + + if (collided < 1) + jumpkeydown = 0; + if (collided > .8 && jumppower >= 5 || + distsq(&coords, &Person::players[0]->coords) > 400 && + onterrain && + creature == rabbittype) + jumpkeydown = 1; + //TODO: why are we controlling the human? + if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) + Person::players[0]->jumpkeydown = 0; + if (Person::players[0]->animTarget == jumpdownanim && + distsq(&Person::players[0]->coords, &coords) < 40) + crouchkeydown = 1; + if (jumpkeydown) + attackkeydown = 0; + + if (Tutorial::active) + if (!canattack) + attackkeydown = 0; + + + XYZ facing = coords; + XYZ flatfacing = Person::players[0]->coords; + facing.y += jointPos(head).y * scale; + flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale; + if (occluded >= 2) + if (-1 != Object::checkcollide(facing, flatfacing)) { + if (!pause) + lastseentime -= .2; + if (lastseentime <= 0 && + (creature != wolftype || + weaponstuck == -1)) { + aitype = searchtype; + lastchecktime = 12; + lastseen = Person::players[0]->coords; + lastseentime = 12; + } + } else + lastseentime = 1; + } + } + if (Animation::animations[Person::players[0]->animTarget].height == highheight && + (aitype == attacktypecutoff || + aitype == searchtype)) + if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) { + XYZ test = Person::players[0]->coords; + test.y -= 40; + if (-1 == Object::checkcollide(Person::players[0]->coords, test)) + stunned = 1; + } + //stunned + if (aitype == passivetype && !(numwaypoints > 1) || + stunned > 0 || + pause && damage > superpermanentdamage) { + if (pause) + lastseentime = 1; + targetyaw = yaw; + forwardkeydown = 0; + leftkeydown = 0; + backkeydown = 0; + rightkeydown = 0; + jumpkeydown = 0; + attackkeydown = 0; + crouchkeydown = 0; + throwkeydown = 0; + } + + + XYZ facing; + facing = 0; + facing.z = -1; + + XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0); + facing = flatfacing; + + if (aitype == attacktypecutoff) { + targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords); + targetheadpitch = pitchTo(coords, Person::players[0]->coords); + } else if (howactive >= typesleeping) { + targetheadyaw = targetyaw; + targetheadpitch = 0; + } else { + if (interestdelay <= 0) { + interestdelay = .7 + (float)(abs(Random() % 100)) / 100; + headtarget = coords; + headtarget.x += (float)(abs(Random() % 200) - 100) / 100; + headtarget.z += (float)(abs(Random() % 200) - 100) / 100; + headtarget.y += (float)(abs(Random() % 200) - 100) / 300; + headtarget += facing * 1.5; + } + targetheadyaw = 180 - roughDirectionTo(coords, headtarget); + targetheadpitch = pitchTo(coords, headtarget); + } + } +}