Massassi Forums Logo

This is the static archive of the Massassi Forums. The forums are closed indefinitely. Thanks for all the memories!

You can also download Super Old Archived Message Boards from when Massassi first started.

"View" counts are as of the day the forums were archived, and will no longer increase.

ForumsCog Forum → Why does this relational test pass...what am I missing? (sync AI cog)
Why does this relational test pass...what am I missing? (sync AI cog)
2004-08-31, 2:55 PM #1
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.

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).]
2004-09-01, 9:19 AM #2
you need to reset the target too.
just add target = -1; to the makeai section.

as for the attacking problem, in offense you are calling fireattarget but your message is
called firetarget and the timer with ID 300 is calling firetarget too.
something needs to be changed there.
------------------
Famous last words - "It seemed like a good idea at the time."

[This message has been edited by DSLS_DeathSythe (edited September 01, 2004).]
Famous last words - "It seemed like a good idea at the time."
2004-09-01, 9:51 AM #3
Speak of the devil! Hey thanks again for sending me those cogs about the saber actor. I assure you the header for this cog already has your name on it!

Doh! I knew it was something stupid...of course, that makes sense. It runs through findtarget with the last info and sets all the values I just cleared back again!

I hadn't really looked at firetarget problems but yeah...I was messing with those names when I tried cleaning up the symbols so of course.

Thanks again!

↑ Up to the top!