PDA

View Full Version : Synced Remotes (with a switch) - A more challenging problem



ORJ_JoS
04-09-2005, 12:52 PM
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 [HR] helped us modifying the cog below to what is shown here, and it works.
However, once you activate the switch, the remotes keep respawning. =\
It's only supposed to spawn when one uses the switch ofcourse.

Anyone have any idea how to fix this?




# 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(movetar get), 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(movetar get), 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_JoS
04-12-2005, 06:35 PM
I think it's something with the respawn timer... or am I stating the obvious? It's a lot of code... lol

SG-fan
04-12-2005, 07:51 PM
Could you include a small test level, otherwise I'll have to try to walk you through debugging it.

ORJ_JoS
04-12-2005, 08:17 PM
Yeah, G-Man made a test level for it. I'll upload it to my site and let you know. :)

ORJ_JoS
04-12-2005, 08:23 PM
Remotetest (http://www.freewebs.com/orderofrebornjedi/remotetest.zip)

Thanks for taking a look :)

SG-fan
04-13-2005, 12:51 AM
Fixed.

Actually it wasn't a cog problem. The problem was that you set the cogs health for the remote as 250, but the remote template only had 30 health. When it kept dying before the cog thought it should, it got borked. You can fix this by making a new remote template with 9999 health. Then the cog controls how much health the remote has.

ORJ_JoS
04-13-2005, 07:58 AM
Wow! Thanks! :D

I'd never have figured that out!

But I only know how to make templates for 3do's... not for AI. I'll ask G-Man how to do that.

Could I also fix it by setting the remote's health to 30 in the cog? I think I'll try that first...

Thanks for helping us out :D

SG-fan
04-13-2005, 07:06 PM
Setting the cogs health to 30 or less does fix it.

The template for the remote is the exact same as the template for the remote, except the health variable is now 9999 instead of 30.

ORJ_JoS
04-15-2005, 08:05 AM
Ok, it worked in the test level. But now I added the cog to my 'real' level (changed the remote's template too), and now my JK freezes like 10 seconds after I get in game! It doesnt matter if I call the remote or not. Even if I stand still, the level will totally freeze on me :o

What could be causing this?

SG-fan
04-15-2005, 11:16 PM
Did you try removing the cog just to make sure that it is the problem?

I honestly don't know. Since it's just that level, I can't help fix it without knowing what ALL is in it. I doubt you would want to send me the actual level, so I'll try to walk you through debugging it.
First, check the cog like I already said (remove it, if it crashes, then it's not the cog)

Also, did you make a NEW template or change the old one? If you changed the old one, then undo your changes and make a new template.

ORJ_JoS
04-15-2005, 11:56 PM
The level worked perfectly before I added the cog. (It's the only thing I changed about the level besides the template of the remote. And yes, I modified the original remote template.

I'll try those two things you said, one after the other.

Thanks :)

ORJ_JoS
04-16-2005, 11:10 PM
Allright, the game stopped crashing once I changed the remote template's health to 999.00 instead of 9999.00

Now there's only one odd detail... If I kill the remote with the saber, it wont respawn. If I kill it with a Force Push, it explodes, but it instantly respawns! =\

And I set the health to 30 in the cog setup. When I used to spawn unsynced remotes, they wouldnt respawn after a Force Push.

there's also one other detail... There should be something in the cog that prevents people from tapping the surface multiple times to spawn a lot of remotes in a short time. That's definitely going to crash my big level in which this preview room will eventually be.... meh.

I'd try a sleep command, if only I knew where to put it...lol. Slaw built it into my item spawning cog which I use in this same level.