Greetings fellow massassians!
I know this is my third request in a row, but I think the other two weren't that challenging.
This one however....
G-Man and I are trying to spawn synced remotes with a switch.
HellRaiser
I know this is my third request in a row, but I think the other two weren't that challenging.
This one however....
G-Man and I are trying to spawn synced remotes with a switch.
HellRaiser
Code:
# Jedi Knight Cog Script # # ais_basic_svr.cog # # Basic Synced AI: MOTS Version # # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # AIS Beta .5 # Incomplete, but functional. You may use this in your levels, but # be aware that there may still be a few bugs, and that improved versions # with more features will be coming out. # JK Version. # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # # Nightmare, knud@raex.com # 8/21/99 # ---------------------------------------------------------------------------------------- # Version 0.1 # First Alpha Version # ---------------------------------------------------------------------------------------- # Version 0.15 # Added some failsafes to handle unexpected errors. Increased packets sent, to # try and eliminate lost packet problems. Fixed some bugs in movement and firing. # ---------------------------------------------------------------------------------------- # Version 0.2 # Reworked to reduce lag and lost packet problems. # Also moved all the different messages sent to an paramater of the trigger message, # making assignment of the triggers easier and less prone to error. # ---------------------------------------------------------------------------------------- # Version 0.25 # Added a count to the triggers, to help with the communications with the client cog. # Added a 'team' variable, so that the AI will only attack opposing players. # Upped status to 'Beta', since it's working with no known bugs. # ---------------------------------------------------------------------------------------- # Version 0.27 # Made it so that if the AI is activated by a member of it's team, it will follow that # until activated again or until it finds a target. # ---------------------------------------------------------------------------------------- # Version 0.5 # Added control flags that can be use o control the behaviour of an AI, making seeking, punching, # and sentry AI's, as well as AI's that initialize when an ajoin is crossed instead of at startup. # Also added support for limited lives on the AI. Mostly stuff for co-op. # ======================================================================================== # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # Implementing the code in your level # # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # # At present, all you have to do for a standard fieldtrooper is place both the client # and server cog in jed (make sure to use the MOTS.tpl file included with the cog), # set the integer 'trig' in both cogs, and 'aipos' (a ghost object) in the server cog. # You can get almost any enemy by changing the varibles in the cog. # # The team variable: set to a team number and the AI will not attack players/AI of # that team. 1 = Red, 2 = Gold, 3 = Blue, 4 = Green. Set to greater than 4 to make # it attack everyone. Don't use 0, as that is the team number for neutral players. # You can also use team numbers greater than 4 to make groups of enemies that will # not attack each other, for instace, all ReeYees on team 5, all stormtroopers on team # 6, that way ReeYees can target ST's and vice versa, but ST's won't attack each other # and ReeYees won't attack each other. # # controlflags: this integer is for setting flags that affect the behavior of the AI. # just choose the flags you want then add together all the numbers to arrive at the # value you should enter in JED. # Here's a list of the flags. # # 1 Seeking: The AI will go looking for a target rather than just waiting for one (use only with patrol flag enabled) # 2 Sentry: The AI won't move towards/away from a target, moves only if following a player # 4 Patrol: when seeking, follow a defined path (the frames of the 'seeker' ghost) rather than just wandering # 8 Spawning: generates when a ajoin is crossed, rather than at startup, to reduce lag in co-op levels. # 16 punching: if below minimum range, uses a different weapon # # 'ammo' and 'lives': These integers limit the number of shots an AI can make, and how many times # it will respawn, mostly for co-op levels to make them stop after awhile. Setting them to 0 # makes them unlimited. # # To make an ai 'seek' a target, you need to place another ghost, assign it to 'seeker', and # give it frames to move along the path you want the ai to follow. 'seekframes' is the number # of the last frame. None of these need to be filled in unless you set the control flags to # make the AI seek along a path. Each waypoint should have LOS to the next with no obstacles # between. Also, I would suggest that you use the 'sentry' flag as well, so that it won't wander # far from the path when it finds a target. # # I've provided a list of variables to change to get the troopers with repeaters and a rancor. # You should be able to make almost any enemy by making an ais_* template and setting the # symbols of the cog from JED. # # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # To make a fieldtrooper with repeater: # # aipos = a ghost in your level, the place where you want the AI to be # trig = a number used as a trigger only in this cog # controlflags = 16 # standoffdist = 0.5 # arriveddist = 1.0 # minfirerate = 0.25 # maxfirerate = 1.25 # drop1 = +drepeatergun # drop2 = +dpowercell # aitpl = ais_st3 # trig = whatever you set the server cog's trig to # firesnd = repeat-1.wav # weapon = +repeaterball # # Leave all other variables at thier defualt values. # # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # # ======================================================================================== # =-=-=-=-=-=-=-=-= # # Notes on the Code # # =-=-=-=-=-=-=-=-= # # # This is a beta: you may use this cog in your levels, but I will be releasing new # versions with added features. # # Planned improvements include: # # Support for force powers like pull, grip, and deadlysight. # # Support for multiple weapons, close range weapons (such as punching) # and a special version for MP Dark Jedi (maybe) # ======================================================================================== symbols message startup message timer message damaged message pulse message activated message crossed thing aipos nolink thing ai mask=-1 local int trig int team=0 int controlflags=0x10 thing seeker int seekframes flex seekspeed=120.0 local flex sightdist=5.0 flex standoffdist=.75 flex arriveddist=1.5 flex movespeed=0.35 flex damage_modifier=.75 flex minfirerate=.75 flex maxfirerate=4.5 flex maxrange=4.5 flex minrange=.3 flex punchrange=.25 flex lead=0.4 flex respawndelay=10.0 int hitpoints=250 int healrate=5 int ammo=0 int lives=0 int killpnts=1 int vision=225 template drop1=+dstrifle template drop2=+denergycell template aitpl=ais_st2 surface ajoin0 surface ajoin1 surface ajoin2 keyframe FireKey=stfire.key keyframe PunchKey=s2club.key keyframe HurtKey=sthit.key keyframe DieKey=stdie.key sound firesnd=pistol-1.wav sound punchsnd=swingfist01.wav sound HurtSnd=i00s127z.wav sound DieSnd=i00s129z.wav template weapon=+ais_laser template punch=+ais_punch thing target local thing movetarget local thing victim local thing killer local thing player local sector sec0 local flex damage_type local flex damage_amount local flex targetswitch local flex Dot local flex MaxDot local int statflags local int aimodeflags local int LOScountdown=0 local int hp local int weapon local int curframe local int shotcount=0 local int hitcount=0 local int incarnation=0 local vector firepos local vector firevec local vector movevec local vector movepos local vector interceptvec local vector dodgevec local vector gunoffset local int debug=0 surface SurfActivate end # ======================================================================================== code # ======================================================================================== spawnAI: # _________________________________________________________________________________ # # INITIALIZATION # _________________________________________________________________________________ # # Create the AI thing and capture it so that the cog recieves the # 'damaged' messages. Set the initial 'statflags' and 'aiflags' # settings and start the pulse. # _________________________________________________________________________________ if(BitTest(controlflags, 0x8)) return; if(!IsMulti() || IsServer()) ai = CreateThing(aitpl, aipos); CaptureThing(ai); SetThingUserData(ai, team); movetarget = aipos; hp = hitpoints; statflags = 0x3; aiflags = 0x2; SetPulse(.5); target = -1; shotcount = 0; hitcount = 0; incarnation = 0; gunoffset = GetThingFireOffSet(ai); SetThingVel(ai, '0 .2 0'); if(debug) { jkStringClear(); jkStringConcatInt(trig); jkStringConcatAsciiString("s:startup"); jkStringOutput(-1, -1); } if(BitTest(controlflags, 0x1)) { curframe = 0; movetarget = seeker; aiflags = BitSet(aiflags, 0x80); TeleportThing(seeker, aipos); SkipToFrame(seeker, 0, seekspeed); } return; # ======================================================================================== # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # AJOIN CROSSED # _________________________________________________________________________________ # # If one of the ajoins is crossed, call the initialization routine. # _________________________________________________________________________________ crossed: controlflags = BitClear(controlflags, 0x8); call SpawnAI; return; # ======================================================================================== pulse: # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # PULSE # _________________________________________________________________________________ # # If it isn't alive, don't do anything at all. # Syncronize the position of the thing so it's in the same place on all computers. # Heal the AI if it's been hurt, this keeps it from wearing down by attrition. # _________________________________________________________________________________ if(BitTest(aiflags, 0x1)) return; SyncThingPos(ai); if(hp < hitpoints) hp = hp + healrate; # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # PULSE: LOOK FOR TARGET # _________________________________________________________________________________ # # If the AI doesn't have a target, cycle through all the things in view and look # for opponets. If a opponet is found, set him/her as the target, adjust the AI # and status flags, and begin firing at random intervals. # _________________________________________________________________________________ if(BitTest(aiflags, 0x2)) { victim = -1; maxDot = sightdist + 1; victim = FirstThingInView(ai, 225, 5.5, 0x404); while(victim != -1) { if((HasLOS(ai, victim)) && ((GetThingType(victim) == 10 && GetPlayerTeam(victim) != team) || (GetThingType(victim) == 2 && GetThingUserData(victim) != team)) && (VectorDist(GetThingPos(ai), GetThingPos(victim)) <= sightdist) && (victim != ai)) { dot = VectorDist(GetThingPos(ai), GetThingPos(victim)); if(dot < maxDot) { target = victim; maxDot = dot; } } victim = NextThingInView(); } if(target != -1) { if(BitTest(controlflags, 0x1)) StopThing(seeker); movetarget = target; aiflags = BitClear(aiflags, 0x2); aiflags = BitSet(aiflags, 0x8); aiflags = BitSet(aiflags, 0x20); if(BitTest(aiflags, 0x80)) aiflags = BitClear(aiflags, 0x80); statflags = BitSet(statflags, 0x4); SetTimerEx(minfirerate + (rand() * (maxfirerate - minfirerate)), 4, 0.0, 0.0); if(debug) { jkStringClear(); jkStringConcatInt(trig); jkStringConcatAsciiString("s:startup"); jkStringOutput(-1, -1); } } } # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # PULSE: MOVEMENT # _________________________________________________________________________________ # # If the almighty 'aiflags' say to move forward, find a spot a little ahead of the # target (so the AI intercepts the target rather than following the target) and # move towards that spot. If too close to the target, reverse and reduce the # movement vector so that the AI tries to maintain a constant distance. # Follow close to 'movetarget' if following a player who activated the AI or the # seeking route ghost. # _________________________________________________________________________________ if(BitTest(aiflags, 0x20) && !BitTest(controlflags, 0x2)) { interceptvec = VectorNorm(VectorSub(VectorAdd(GetThingPos(movetarget), VectorScale(GetThingVel(movetarget), lead)), GetThingPos(ai))); movevec = VectorSet(VectorX(interceptvec), VectorY(interceptvec), 0.0); SetThingLook(ai, movevec); if(VectorDist(GetThingPos(ai), GetThingPos(movetarget)) < standoffdist) SetThingVel(ai, VectorScale(VectorNorm(GetThingLVec(ai)), -movespeed)); if(VectorDist(GetThingPos(ai), GetThingPos(movetarget)) > (arriveddist)) SetThingVel(ai, VectorScale(VectorNorm(GetThingLVec(ai)), movespeed)); } if(BitTest(aiflags, 0x80)) { if(GetThingType(movetarget) != 10 && BitTest(controlflags, 0x1)) { if(!IsthingMoving(seeker) && VectorDist(GetThingPos(ai), GetThingPos(movetarget)) < .25) { curframe = curframe + 1; if(curframe > seekframes) curframe = 0; SkipToFrame(seeker, curframe, seekspeed); } } if(GetThingType(movetarget) == 10 && !HasLOS(ai, movetarget)) { movetarget = -1; aiflags = BitClear(aiflags, 0x80); } if(HasLOS(ai, movetarget)) { interceptvec = VectorNorm(VectorSub(VectorAdd(GetThingPos(movetarget), VectorScale(GetThingVel(movetarget), lead)), GetThingPos(ai))); movevec = VectorSet(VectorX(interceptvec), VectorY(interceptvec), 0.0); SetThingLook(ai, movevec); if(VectorDist(GetThingPos(ai), GetThingPos(movetarget)) > .25) SetThingVel(ai, VectorScale(VectorNorm(GetThingLVec(ai)), movespeed)); } } # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # PULSE: TARGET CHECK # _________________________________________________________________________________ # # The target is considered 'lost' if it either falls out of range of LOS is lost. # If the target is lost for 8 consecutive pulses (4 sec), dies, or ceases to exist, # reset the status and ai flags and begin looking for a new target. # _________________________________________________________________________________ if(BitTest(aiflags, 0x8)) { if(HasLOS(ai, target)) LOScountdown = 0; if(!HasLOS(ai, target) || VectorDist(GetThingPos(ai), GetThingPos(target)) < sightdist) LOScountdown = LOScountdown + 1; if(LOScountdown >= 8 || (GetThingFlags(target) & 0x200)) { target = -1; movetarget = -1; aiflags = BitSet(aiflags, 0x2); aiflags = BitClear(aiflags, 0x8); aiflags = BitClear(aiflags, 0x20); statflags = BitClear(statflags, 0x4); if(BitTest(controlflags, 0x1)) { movetarget = seeker; aiflags = BitSet(aiflags, 0x80); SkipToFrame(seeker, curframe, seekspeed); } if(debug) { jkStringClear(); jkStringConcatInt(trig); jkStringConcatAsciiString("s:target lost"); jkStringOutput(-1, -1); } } } # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # PULSE: FAILSAFES # _________________________________________________________________________________ # # These are just checks to catch and reset the AI if anything unexpected should # happen to it, such as if it were destroyed or changed by another cog. # Also check to see if the AI is in a pit, if so, respawn. # _________________________________________________________________________________ sec0 = GetThingSector(ai); if((ai == -1) || (GetThingTemplate(ai) != aitpl) || (GetSectorFlags(sec0) & 0x40)) { target = -1; if(ai > -1) { StopThing(ai); ReleaseThing(ai); DestroyThing(ai); } if(!IsMulti() || IsServer()) ai = GetGuidThing(CreateThing(aitpl, aipos)); CaptureThing(ai); incarnation = incarnation + 1; SetThingUserData(ai, team); hp = hitpoints; shotcount = 0; hitcount = 0; statflags = 0x3; aiflags = 0x2; SetThingVel(ai, '0 .2 0'); if(BitTest(controlflags, 0x1)) { movetarget = seeker; aiflags = BitSet(aiflags, 0x80); TeleportThing(seeker, aipos); curframe = 0; SkipToFrame(seeker, 0, seekspeed); } if(debug) { jkStringClear(); jkStringConcatInt(trig); jkStringConcatAsciiString("s:failsafe reset"); jkStringOutput(-1, -1); } } # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # return; # ======================================================================================== damaged: # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # DAMAGED # _________________________________________________________________________________ # # Only take damage if the the AI is alive and it's damaged by an oppnet. If the damage # fit the type mask, apply the damage modifier. Reduce the hitpoints by final result. # _________________________________________________________________________________ if(!BitTest(statflags, 0x1)) return; killer = GetThingParent(GetSourceRef()); if((killer == -1) || ((GetThingType(killer) == 10 && GetPlayerTeam(killer) == team) || (GetThingType(killer) == 2 && GetThingUserData(killer) == team))) return; damage_type = GetParam(1); damage_amount = GetParam(0); if(BitTest(damage_type, 0x15)) damage_amout = damage_amount * damage_modifier; hp = hp - damage_amount; # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # DAMAGED: HURT # _________________________________________________________________________________ # # If the AI is still alive after taking damage, send a trigger to do the hurt effects, # and if possibly switch targets to the player damaging it (so if it's not vulnerable # to others player while pursuing a target). Always select a target if it has none. # _________________________________________________________________________________ if(hp > 0) { targetswitch = damage_amount + (rand() * 80); if((targetswitch > 100) || (!BitTest(statflags, 0x4)) && ((GetThingType(killer) == 10 && GetPlayerTeam(killer) != team) || (GetThingType(killer) == 2 && GetThingUserData(killer) != team))) { if(BitTest(controlflags, 0x1)) StopThing(seeker); target = killer; movetarget = killer; LOScountdown = 8; if(BitTest(aiflags, 0x2)) aiflags = BitClear(aiflags, 0x2); if(!BitTest(aiflags, 0x8)) aiflags = BitSet(aiflags, 0x8); if(!BitTest(aiflags, 0x20)) aiflags = BitSet(aiflags, 0x20); if(BitTest(aiflags, 0x80)) aiflags = BitClear(aiflags, 0x80); if(!BitTest(statflags, 0x4)) statflags = BitSet(statflags, 0x4); KillTimerEx(4); SetTimerEx(minfirerate + (rand() * (maxfirerate - minfirerate)), 4, 0.0, 0.0); } hitcount = hitcount + 1; PlayKey(ai, HurtKey, 2, 32); PlaySoundThing(HurtSnd, ai, 1.0, -1, -1, 0); if(debug) { jkStringClear(); jkStringConcatInt(trig); jkStringConcatAsciiString("s:damaged - hurt"); jkStringOutput(-1, -1); } } # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # DAMAGED: DEATH # _________________________________________________________________________________ # # If the AI's hitpoints have been reduced to zero, set the flags so as to prevent # the AI from doing anything, send the trigger to do the death effects, add a point # and a kill to the player who fragged it, kill the pulse, and set the respawn timer. # _________________________________________________________________________________ if(hp <= 0) { if(BitTest(controlflags, 0x1)) StopThing(seeker); target = -1; ReleaseThing(ai); movetarget = aipos; statflags = 0x0; aiflags = 0x1; SetPulse(0); KillTimerEx(4); CreateThing(drop1, ai); CreateThing(drop2, ai); SetPlayerScore(killer, GetPlayerScore(killer) + killpnts); SetPlayerKills(killer, GetPlayerKills(killer) + killpnts); SyncScores(); SetThingMass(ai, 0); SetThingFlags(ai, 0x200); StopThing(ai); PlayKey(ai, DieKey, 1, 32); PlaySoundThing(DieSnd, ai, 1.0, -1, -1, 0); SetTimerEx(GetKeyLen(DieKey), 10, 0.0, 0.0); if(lives == 1) { SetPulse(0); aiflags = 0x0; statflags = 0x0; controlflags = 0x0; } if(lives != 1) { SetTimerEx(respawndelay, 7, 0.0, 0.0); if(lives > 1) lives = lives - 1; } if(debug) { jkStringClear(); jkStringConcatInt(trig); jkStringConcatAsciiString("s:damaged - death"); jkStringOutput(-1, -1); } } # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # return; # ======================================================================================== timer: # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # TIMER: FIRE WEAPON # _________________________________________________________________________________ # # Check that the AI is alive, has a target, has ammo, and is attacking. # Lead the target a little, don't aim right at it, but a little in front of it. # Create a Projectile and send a trigger to do the fire effects. Clear the flags # after short delay so the AI can move again. # _________________________________________________________________________________ if(GetSenderID() == 4) { if(BitTest(aiflags, 0x8)) { if((ammo == 0 || shotcount < ammo) && ((VectorDist(GetThingPos(ai), GetThingPos(target)) > minrange) && (VectorDist(GetThingPos(ai), GetThingPos(target)) < maxrange) && (HasLOS(ai, target)))) { StopThing(ai); firepos = VectorAdd(GetThingPos(target), VectorScale(GetThingVel(target), lead)); firevec = VectorNorm(VectorSub(firepos, GetThingPos(ai))); SetThingLook(ai, firevec); shotcount = shotcount + 1; FireProjectile(ai, weapon, firesnd, 8, gunoffset, '0 0 0', 1.0, 0x20, 25, .75); PlayKey(ai, FireKey, 2, 32); } if((VectorDist(GetThingPos(ai), GetThingPos(target)) < punchrange && HasLOS(ai, target)) && BitTest(controlflags, 0x10)) { StopThing(ai); firepos = VectorAdd(GetThingPos(target), VectorScale(GetThingVel(target), lead)); firevec = VectorNorm(VectorSub(firepos, GetThingPos(ai))); SetThingLook(ai, firevec); shotcount = shotcount + 1; FireProjectile(ai, punch, punchsnd, 8, gunoffset, '0 0 0', 1.0, 0x20, 25, .75); PlayKey(ai, punchKey, 2, 32); } SetTimerEx(minfirerate + (rand() * (maxfirerate - minfirerate)), 4, 0.0, 0.0); if(debug) { jkStringClear(); jkStringConcatInt(trig); jkStringConcatAsciiString("s:fire"); jkStringOutput(-1, -1); } } return; } # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # # _________________________________________________________________________________ # # TIMER: RESPAWN # _________________________________________________________________________________ # # Release and destroy the dead AI thing, create and capture a new one. # Set all the numbers, and restart the pulse. # _________________________________________________________________________________ if(GetSenderID() == 7) { if(ai != -1) DestroyThing(ai); if(!IsMulti() || IsServer()) ai = GetGuidThing(CreateThing(aitpl, aipos)); CaptureThing(ai); SetThingUserData(ai, team); incarnation = incarnation + 1; hp = hitpoints; shotcount = 0; hitcount = 0; statflags = 0x3; aiflags = 0x2; SetPulse(.5); SetThingVel(ai, '0 .2 0'); SendTrigger(-1, trig, 1, GetGuidThing(ai), incarnation, 0); SendTrigger(-1, trig, 1, GetGuidThing(ai), incarnation, 0); SendTrigger(-1, trig, 1, GetGuidThing(ai), incarnation, 0); if(BitTest(controlflags, 0x1)) { movetarget = seeker; aiflags = BitSet(aiflags, 0x80); TeleportThing(seeker, aipos); curframe = 0; SkipToFrame(seeker, 0, seekspeed); } if(debug) { jkStringClear(); jkStringConcatInt(trig); jkStringConcatAsciiString("s:respawn"); jkStringOutput(-1, -1); } return; } # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # if(GetSenderID() == 10) { DestroyThing(ai); } # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # return; activated: if((GetSenderType() == 6) && (GetSenderRef() == SurfActivate)) { controlflags = BitClear(controlflags, 0x8); call SpawnAI; return; } # _________________________________________________________________________________ # # ACTIVATION # _________________________________________________________________________________ # # If a player on the AI's team activates it with the spacebar, follow that character # until activated again or until it finds a target. # _________________________________________________________________________________ if(GetSenderRef() == ai) { player = GetSourceRef(); if((GetPlayerTeam(player) == team) && (BitTest(aiflags, 0x2))) { if(!BitTest(aiflags, 0x80)) { movetarget = player; aiflags = BitSet(aiflags, 0x80); if(debug) { jkStringClear(); jkStringConcatInt(trig); jkStringConcatAsciiString("s:follow"); jkStringOutput(-1, -1); } return; } if(BitTest(aiflags, 0x80)) { movetarget = -1; aiflags = BitClear(aiflags, 0x80); if(debug) { jkStringClear(); jkStringConcatInt(trig); jkStringConcatAsciiString("s:stop"); jkStringOutput(-1, -1); } return; } } } return; # ======================================================================================== end
ORJ / My Level: ORJ Temple Tournament I