Below is my WIP synced saber ai cog. For some reason, after the AI is killed and respawns is runs the sector of the code that seeks an old target, which is good...but should not be happening after they die! It doesn't make sense because when its killed its flags are reset, oldtarget is set to -1 and oldtargetpos is set to the ai's pos. Not only should it fail the relational test for the flags and not ever even run that code in the first place...but if it did, the code should result in the ai going nowhere.
But no, it seeks out the oldtargetpos right after respawning. Why? Am I missing something?
The AI also no longer attacks, which it once did great...I'm not sure how I broke that.
Btw...this includes the clever little hack by DSLS_DeathSythe to make sabers work on spawned actors.
[This message has been edited by Wave_Of_Mutilation (edited August 31, 2004).]
But no, it seeks out the oldtargetpos right after respawning. Why? Am I missing something?
The AI also no longer attacks, which it once did great...I'm not sure how I broke that.
Btw...this includes the clever little hack by DSLS_DeathSythe to make sabers work on spawned actors.
Code:
flags=0x80 symbols message startup message timer message damaged message killed message pulse message activated message touched thing aipos nolink int trig int team=0 flex movespeed=0.35 flex firerate=1.0 flex awarerange=4.5 flex maxrange=4.5 flex minrange=.3 flex respawndelay=10.0 int lives=0 template drop1=+dstrifle template drop2=+denergycell template aitpl=ais_st2 keyframe AttackKey=kycharge.key keyframe AttackKey2=s5punch.key keyframe AttackKey3=s5punch.key sound firesnd=hsblaster.wav sound firesnd2=hsblaster.wav sound firesnd3=hsblaster.wav #used internally thing ai local mask=0xfff thing oldtarget local thing player local vector oldtargetpos local flex disttotarg local vector relpos local int aimode local int stopcount local int targetok local int targetpriority local int newtargetpriority local flex dist local flex mindist local thing target local thing newtarget local flex Dot local flex MaxDot local flex damage local int damagetype local thing damager local model saberMesh=sabg.3do local material tip_mat=saberblue0.mat local material side_mat=saberblue1.mat local template tpl_wall=+ssparks_wall local template tpl_blood=+ssparks_blood local template tpl_saber=+ssparks_saber local int debug=0 end # ======================================================================================== code # ======================================================================================== startup: sleep(4.0); print("run"); if(!IsMulti() || IsServer()) call makeai; return; # ======================================================================================== makeai: //if(BitTest(controlflags, 0x8)) return; ai = GetGuidThing(CreateThing(aitpl, aipos)); CaptureThing(ai); //give them a saber jkSetWeaponMesh(ai, saberMesh); jkSetSaberInfo(ai, side_mat, tip_mat, 0.003, 0.001, 0.120, tpl_wall, tpl_blood, tpl_saber); jkSetFlags(ai, 0x5); SetActorFlags(ai, 0x2000); //set move speed AiSetMoveSpeed(ai, movespeed); //team stored in userdata SetThingUserData(ai, team); //we died so forget about who we were after oldtarget = -1; oldtargetpos = aipos; // set to ai start spot aimode = BitSet(aimode, 0x100); // ai alive //run the thing pulse SetPulse(0.1); return; # ======================================================================================== # called from pulse findtarget: newtarget=-1; maxdot = -1; mindist = 100; targetpriority = 0; newtargetpriority = -1; potential = FirstThingInView(ai, 270, 8.0, 0x404); // find (0x404 - player or actor) while(potential != -1) // valid target { targetok = 1; if (GetThingType(potential) == 2 && GetThingUserData(potential) == team) targetok = 0; // target is an actor and is on our team if (GetThingType(potential) == 10 && GetPlayerTeam(potential) == team) targetok = 0; // target is a player and is on our team if (GetThingFlags(potential) & 0x200) targetok = 0; // target is dead if (BitTest(GetSectorFlags(GetThingSector(potential)), 0x40)) targetok = 0; // target in pit if (targetok && potential != ai && HasLOS(ai, potential)) // target is still ok, is not itself and ai can see it { // Work out target priority dist = VectorDist(GetThingPos(ai), GetThingPos(potential)); if (dist > 0 && dist < 1) targetpriority = 6; else targetpriority = 3; // closer targets get higher priority if (damager != -1 && GetThingParent(damager) == potential) targetpriority = 7; // whoever hurt the ai last is higher priority if (targetpriority > newtargetpriority) { newtarget = potential; newtargetpriority = targetpriority; } } potential = NextThingInView(); } if(target != -1) //don't dump a null target to the old target as we use it to find lost targets that are real { //old target will be used to find a foe we lost sight of, but is still near us oldtarget = target; //grab the pos the target is currently at, if we lose the target we will try to find him by going to where he was. aimode = BitSet(aimode, 0x80); //ai now has oldtarget pos to seek from oldtargetpos = GetThingPos(target); } target = newtarget; if (target == -1) // ai doesn't have a target { aimode = BitClear(aimode, 0x40); //no target for ai if(Bittest(aimode,0x80)) // we will seek where a target was last seen first, so look at it AiSetLookPos(ai, oldtargetpos); //if(oldtarget != -1 && VectorDist(GetThingPos(ai), GetThingPos(oldtarget)) < awarerange) //{ //KillTimerEx(500); //SetTimerEx(0.2 + Rand(), 500, -1, -1); // after a short time, find the target again if he is close //print("recover target attempt"); //AiSetLookPos(ai, getthingpos(oldtarget)); //} print("no target"); } else // ai has a target { print("target found"); AiSetFireTarget(ai, target); AiSetLookPos(ai, getthingpos(target)); aimode = BitSet(aimode, 0x40); //ai now has target, allow next part of code } return; # ======================================================================================== # called from pulse offense: if (!Bittest(aimode,0x100)) return; // ai has died if (BitTest(aimode,0x200)) return; // ai is already attacking, timers will handle repeat attacks from now on if(!Bittest(aimode,0x40) && !Bittest(aimode,0x80)) return; //if we don't have a target in our sights or an old pos to go after, bail out //disttotarg = VectorDist(GetThingPos(ai), GetThingPos(target)); if(Bittest(aimode,0x40) && VectorDist(GetThingPos(ai), GetThingPos(target)) < minrange && HasLOS(ai, target)) //meets requirements to be attacked now, has target, distance is good, has LOS call fireattarget; else call movetotarget; return; # ======================================================================================== # called from offense movetotarget: if (!BitTest(aimode, 0x100)) // ai dead or no target, timer indicates they where lost, // but firetarget must remove flag return; //AiSetLookPos(ai, getthingpos(target)); if(Bittest(aimode,0x40)) //go after the target if we have one AiSetMovePos(ai, GetThingPos(target)); else //if we have no target, proceed to the old targets pos if(Bittest(aimode,0x80)) { if(VectorDist(GetThingPos(ai), oldtargetpos) < 0.1) //allow for some margin of error here, because of different sized actors { if(VectorDist(GetThingPos(ai), GetThingPos(ai)) < awarerange) AiSetLookPos(ai, getthingpos(oldtarget)); //once we arrive at last know pos, take once last glance attempt to find our lost target oldtarget = -1; //give up on target aimode = BitClear(aimode, 0x80); //no longer have an old target oldtargetpos = GetThingPos(ai); //set us as arrived } else AiSetMovePos(ai, oldtargetpos); //print("running seek old code"); } else //this probably won't ever get called return; if (VectorY(GetThingVel(ai)) < 0.01) // bot is not moving forward { stopcount = stopcount + 1; if (stopcount == 30) { ApplyForce(ai, VectorScale(VectorSub(GetThingLVec(ai), '0 0 -90'), 3.0)); // force bot to jump stopcount = 0; } } else stopcount = 0; return; # ======================================================================================== # called from offense firetarget: //return; // hack to stop ais firing - testing only KillTimerEx(300); // make sure no other 'fire' target is active, stop attack loop if (!BitTest(aimode, 0x100) || !Bittest(aimode, 0x40)) // ai dead or no target, timer indicates they where lost, // but firetarget must remove flag { aimode = BitClear(aimode, 0x200); //turn off attacking mode and cancel return; } AiSetMovePos(ai, getthingpos(ai)); aimode = BitSet(aimode, 0x200); // ai is now attacking, turn on attack mode flag //disttotarg = VectorDist(GetThingPos(ai), GetThingPos(target)); //relpos = VectorSet("0.0","0.0", VectorZ(GetThingPos(target))-VectorZ(GetThingPos(ai))); // work out relative position of //target to ai if(VectorDist(GetThingPos(ai), GetThingPos(target)) < minrange && HasLOS(ai, target)) // reality check, can we still attack the //target from here? { //AiSetLookPos(ai, getthingpos(target)); print("attack"); SetThingType(ai, 10); jkEnableSaber(ai, 50.0, 0.3, 0.5); SetThingType(ai, 2); PlayKey(ai, AttackKey[Rand() * 3], 2, 0x38); PlaySoundThing(firesnd[Rand() * 3], ai, 1.0, -1.0, -1.0, 0x80); SetTimerEx(firerate, 300, -1, -1); // wait for a short time before firing again } else { aimode = BitClear(aimode,0x200); // ai is no longer attacking, turn off attack flag KillTimerEx(300); // make sure no other 'fire' target is active, stop attack loop } return; # ======================================================================================== pulse: if(!IsMulti() || IsServer()) { //setpulse(0); call findtarget; call offense; if(IsMulti()) syncthingpos(ai); } return; return; # ======================================================================================== damaged: if(!IsMulti() || IsServer()) { damage = GetParam(0); damagetype = GetParam(1); damager = getsourceref(); // projectile - attacker=GetThingParent() if (damager != -1 && (GetThingType(GetThingParent(damager)) == 2 || GetThingType(GetThingParent(damager)) == 10)) // attacker is another ai or player AiSetLookPos(ai, getthingpos(GetThingParent(damager))); // briefly look at who damaged the ai //if (BitTest(gamemode,0x8) && ((GetThingType(GetThingParent(damager)) == 10 && GetPlayerTeam(GetThingParent(damager)) == team) || (GetThingType(GetThingParent(damager)) == 2 && GetThingUserData(GetThingParent(damager)) == team))) // damage = 0; ReturnEx(damage); } return; # ======================================================================================== touched: if (GetThingType(GetThingParent(GetSourceRef())) == 2 || GetThingType(GetThingParent(GetSourceRef())) == 10) // attacker is another ai or player AiSetLookPos(ai, getthingpos(GetThingParent(GetSourceRef()))); // briefly look at who damaged the ai return; # ======================================================================================== blockstuff: return; if (curweap == 10 && BitTest(aimode,0x200000)) // ai has saber - check if it can block { // Check for saber blocking dot = ThingViewDot(ai, getthingparent(damager)); if ((BitTest(damagetype, 0x10) && dot > 0.9 && dot < 1.1 && difficulty < 2) || (BitTest(damagetype, 0x10) && dot > 0.5 && dot < 1.5 && difficulty < 4) || (BitTest(damagetype, 0x10) && dot > 0.3 && dot < 1.7)) // attacker has saber & ai is facing attacker { SendTrigger(-1, 2100, aiid, ai, -1, -1); // send trigger to client to play saber block animation ReturnEx(0); return; } if ((BitTest(damagetype, 0x2) && dot > 0.9 && dot < 1.1 && difficulty < 2) || (BitTest(damagetype, 0x2) && dot > 0.5 && dot < 1.5 && difficulty < 4) || (BitTest(damagetype, 0x2) && dot > 0.3 && dot < 1.7)) // attacked by energy weapon & ai is _mainly_ facing attacker { SendTrigger(-1, 2100, aiid, ai, getthingtemplate(damager), -1); // send trigger to play saber block animation & deflect projectile ReturnEx(0); return; } } return; # ======================================================================================== killed: if(!IsMulti() || IsServer()) { print("killed"); setpulse(0); StopThing(ai); aimode = 0; // ai no longer alive, clear all flags KillTimerEx(300); // stop firing at target? KillTimerEx(400); // stop checking if ai is in a pit? KillTimerEx(500); // no save for find ReleaseThing(ai); SetTimerEx(respawndelay, 10, -1, -1); // respawn ai } return; # ======================================================================================== timer: if (GetSenderId() == 10) // respawn { call makeai; } else if (GetSenderId() == 130) // allow ai to run full speed again after slowdown { aimode=BitClear(aimode, 0x100000); } else if (GetSenderId() == 170) // Forget who damaged ai { damager = -1; } else if (GetSenderId() == 300) // fire again at target { call firetarget; } else if (GetSenderId() == 450) // Allow ai to block again { aimode = BitClear(aimode, 0x2000); } else if (GetSenderId() == 500) // try to find a lost target again { if (!Bittest(aimode,0x40) && Bittest(aimode,0x100)) { print("recover target"); AiSetLookPos(ai, getthingpos(oldtarget)); } //oldtarget = -1; //do not try again } return; # ======================================================================================== end
[This message has been edited by Wave_Of_Mutilation (edited August 31, 2004).]