Attacking Order
- metal_head
- Posts: 1244
- Joined: Sat Jan 05, 2008 8:31 pm
- Location: Bulgaria,Sofia
- Contact:
Attacking Order
OK,I know that if a pawn is hostile to the player and to other groups,he attacks the player first and than when the plyer is killed the pawn starts to attack the other pawn groups,but it attacks the first pawn than the second .I mean if there is a player and pawns "Pawn1" "Pawn2" "Pawn3" and if pawn 1 is hostile to everything,it attacks first Pawn2 and than Pawn3 (at least I think it's like that) so the pawn attacks the pawns by their number in the pawn list.
Is it possible to make the pawn attack the nearest pawn(or player),not the smallest number in the pawn list or not the player first? I'm working on the perfectai,so I was thinking,it's maybe something in the "Spawn[ ()" order...
Is it possible to make the pawn attack the nearest pawn(or player),not the smallest number in the pawn list or not the player first? I'm working on the perfectai,so I was thinking,it's maybe something in the "Spawn[ ()" order...
Last edited by metal_head on Wed Aug 20, 2008 11:25 am, edited 1 time in total.
-
- Posts: 335
- Joined: Sat Feb 09, 2008 5:47 pm
- Location: Lanzarote/Canary Islands/Spain
Re: Attacking
Try checking the distance commands, and the target commands. Sorry I can't do anything more than tellng you this, but I'm kind of busy
- metal_head
- Posts: 1244
- Joined: Sat Jan 05, 2008 8:31 pm
- Location: Bulgaria,Sofia
- Contact:
Re: Attacking
well,maybe they need some editing..but I can't get what should I do to make this.I think it's something simple,but I don't know what's it
- metal_head
- Posts: 1244
- Joined: Sat Jan 05, 2008 8:31 pm
- Location: Bulgaria,Sofia
- Contact:
Re: Attacking
OK,here's the attack command in the script,but I looked and I looked at it,but I couldn't get it..where does it say which pawn to attack first (reminding that I want the pawn to attack the nearest enemy no matter is it the player or not). I need a little help please
Code: Select all
monster_missile[ ()
{
self.ThinkTime = 0.3;
if(self.health<=0)
{
self.think = "death_biz";
return 0;
}
if((self.in_pain = true) and (random(1,100)<PAINPERCENT))
{
AddExplosion("headshot",GetLastBoneHit(),0,0,0);
}
exist = EnemyExist(DAMAGEATTRIBUTE);
if(exist < 2)
{
SetHoldAtEnd(false);
HighLevel("LostTarget"); // enemy is dead and gone
return 0;
}
if(exist = 2)
{
SetHoldAtEnd(false);
HighLevel("LostTarget"); // enemy is dead but body remains
return 0;
}
if(enemy_vis = false)
{
self.think = LOSTFUNC; // lost sight of enemy
lost_time = time + LOSTTIME;
SetHoldAtEnd(false);
return 0;
}
if(self.player_Y>self.current_Y)
{
Animate(SHOOTUP);
AddExplosion(FLASH,"Bip01 R Hand",0,0,0);
FireProjectile(PROJECTILE, FIREBONE, OFFSETX, OFFSETY, OFFSETZ, DAMAGEATTRIBUTE);
PlaySound("shotfire.wav", 500);
SetHoldAtEnd(false);
self.ThinkTime = 0.3;
}
if(self.player_Y<self.current_Y)
{
Animate(SHOOTDOWN);
AddExplosion(FLASH,"FIREBONE",0,0,0);
FireProjectile(PROJECTILE, FIREBONE, OFFSETX, OFFSETY, OFFSETZ, DAMAGEATTRIBUTE);
PlaySound("shotfire.wav", 500);
SetHoldAtEnd(false);
self.ThinkTime = 0.3;
}
if(enemy_range>MISSILERANGE)
{
Animate(MISSILEATTACK);
FireProjectile(PROJECTILE, FIREBONE, OFFSETX, OFFSETY, OFFSETZ, DAMAGEATTRIBUTE);
fire_delay = time + FIREDELAY; // set firing delay
PlaySound("shotfire.wav", 500);
self.think = RUNFUNC; // too far away so run toward
SetHoldAtEnd(false);
return 0;
}
if(skill_time<time) // update according to skill level
{
UpdateTarget(); // update target location
skill_time = time + (SKILL*0);
ai_face(); // face enemy while attacking
}
if(fire_delay<time) // delay after animation starts before firing
{
FireProjectile(PROJECTILE, FIREBONE, OFFSETX, OFFSETY, OFFSETZ, DAMAGEATTRIBUTE);
fire_delay = time + 1000; // set delay well ahead so it is ignored
PlaySound("shotfire.wav", 500);
}
if(self.animate_at_end = true)
{
if(attack_delay < time)
{
//self.think = RUNFUNC; // no
self.think = "monster_missile_start";
SetHoldAtEnd(false);
self.ThinkTime = 0;
}
}
} ]
Re: Attacking Order
The thing with perfectAI is that it doesn't "see" anything else than its current target when attacking. It can only acquire new targets with FindTargetOrder(); which is a high level command.
In low level the only way to set a target is with the SetTarget() command (or TargetPlayer() if you wanna target the player). And for that you need to know the entityname of the pawn you want to target. So there is no command that somehow scans the area and looks for a target like in high level.
So, what can we do?
We can loop through every enemy pawn and manually see if it's alive, if it can be seen and if it's within the sight range. For this you need to name every enemy like enemy1 enemy2 enemy3 etc. And every friend friend1 friend2 friend3 etc. This way we know the entityname of every single pawn in the level. They're always enemy or friend plus a number to separate it from everyone else.
Then let's write a little loop that checks if any enemy pawn is targetable (so this would go to the script of the friendly pawns):This order should give the pawn a new target. I can't guarantee it works since I haven't tested it. Now, every time you want the pawn to pick a new target you would just use newtarget();. For example, if you want to take a new target every 5 seconds you would write:
Oh, and there are all these new variables and stuff in the script so you better introduce them in the beginning of the script:
And lastly, I recommend being careful with this thing. If you have a dozen pawns scanning for enemies every frame it just might affect your frame rate "a bit".
Hope this makes sense and helps you.
The monster_missile order (or any other low level order) has nothing to do with this. When in low level the pawn just attacks the target it got in high level. And if it loses or kills the target it goes back to high level so it can execute FindTargetOrder() again and find a new target.FindTargetOrder(float Distance, string Order, string Attribute);
Search the area within Distance of the Pawn for a target to attack. The target must have the attribute Attribute present to become a target. When a target is acquired the Script Order Order is executed.
In low level the only way to set a target is with the SetTarget() command (or TargetPlayer() if you wanna target the player). And for that you need to know the entityname of the pawn you want to target. So there is no command that somehow scans the area and looks for a target like in high level.
So, what can we do?
We can loop through every enemy pawn and manually see if it's alive, if it can be seen and if it's within the sight range. For this you need to name every enemy like enemy1 enemy2 enemy3 etc. And every friend friend1 friend2 friend3 etc. This way we know the entityname of every single pawn in the level. They're always enemy or friend plus a number to separate it from everyone else.
Then let's write a little loop that checks if any enemy pawn is targetable (so this would go to the script of the friendly pawns):
Code: Select all
newtarget[ ()
{
for targetnumber=0 to MAXENEMYPAWNS step 1 //loop through all enemy pawns
{
targetname = StringCopy("enemy" # targetnumber); //create the entityname of the _possible_ new target
if(FastDistance(targetname,SIGHTRANGE)) //if the new target is inside sight range
{
if(IsEntityVsible(targetname)) //if the new target is visible
{
SetTarget(targetname);
if(EnemyExist(DAMAGEATTRIBUTE) < 3) //if the new target isn't alive
{
SetTarget(""); //no target
}
else
{
break; //new target is alive so keep it and break out of the loop
}
}
}
}
return;
} ]
Code: Select all
if(newtargettimer < self.time)
{
newtarget();
newtargettimer = self.time +5;
}
Code: Select all
MAXENEMYPAWNS [20]
targetnumber [0]
targetname []
//if you use the timer
newtargettimer [0]
And lastly, I recommend being careful with this thing. If you have a dozen pawns scanning for enemies every frame it just might affect your frame rate "a bit".
Hope this makes sense and helps you.
Pain is only psychological.
- metal_head
- Posts: 1244
- Joined: Sat Jan 05, 2008 8:31 pm
- Location: Bulgaria,Sofia
- Contact:
Re: Attacking Order
I'll test it,just a little explanation I need:
so now,I put this in the script and than in the world editor I'll have to name every pawn entity,right?
so now,I put this in the script and than in the world editor I'll have to name every pawn entity,right?
Re: Attacking Order
You don't need to name every pawn. Just the enemies and allies.
Pain is only psychological.
- metal_head
- Posts: 1244
- Joined: Sat Jan 05, 2008 8:31 pm
- Location: Bulgaria,Sofia
- Contact:
Re: Attacking Order
sorry,that's what I ment,ok I'll try it,thanks!
- metal_head
- Posts: 1244
- Joined: Sat Jan 05, 2008 8:31 pm
- Location: Bulgaria,Sofia
- Contact:
Re: Attacking Order
amm,I didn't get where to put this...
Code: Select all
if(newtargettimer < self.time)
{
newtarget();
newtargettimer = self.time +(ammound of time);
}
Re: Attacking Order
Modified it a bit. Now it can target the player and has correct variables from perfectai (ALERTSIGHTDIST, HOSTILEPLAYER). Also returns true or false depending on if it found a new target.
So for example if you wanted to look for another target after losing sight of the current, one you'd replace:
(this can be found in all the attacking orders. monster_missile, monster_melee etc.)with
The timer thing was just an example of how you could use it. You could just put the timer in any of the attacking orders (monster_melee, monster_missile) and the pawn would find a new target every X seconds. For example:
Would search for enemies every 2 seconds and whenever the pawn loses the current target.
Note: I haven't actually tested the script so make sure you run it with the console on so you see if there are any syntax errors. I'll try to test it when I have the time.
Code: Select all
newtarget[ ()
{
for targetnumber=0 to MAXENEMYPAWNS step 1 //loop through all enemy pawns
{
targetname = StringCopy("enemy" # targetnumber); //create the entityname of the _possible_ new target
if(FastDistance(targetname,ALERTSIGHTDIST)) //if the new target is inside sight range
{
if(IsEntityVsible(targetname)) //if the new target is visible
{
SetTarget(targetname);
if(EnemyExist(DAMAGEATTRIBUTE) < 3) //if the new target isn't alive
{
SetTarget(""); //no target
}
else
{
return true; //new target is alive so keep it and break out of the loop
}
}
}
}
if(HOSTILEPLAYER) //if hostile to player
{
if(FastDistance("Player",ALERTSIGHTDIST)) //if the player is inside sight range
{
if(IsEntityVsible("Player")) //if player is visible
{
TargetPlayer();
if(EnemyExist(DAMAGEATTRIBUTE) < 3) //if the player isn't alive
{
SetTarget(""); //no target
}
else
{
return true; //new target is alive so keep it and break out of the loop
}
}
}
}
return false; //no target so return false
} ]
Sorry, it seems I didn't explain it very well. Whenever you want the pawn to find a new target you just need to put:amm,I didn't get where to put this...
Code: Select all
newtarget();
(this can be found in all the attacking orders. monster_missile, monster_melee etc.)
Code: Select all
if(enemy_vis = false)
{
self.think = LOSTFUNC; // lost sight of enemy
lost_time = time + LOSTTIME;
SetHoldAtEnd(false);
return 0;
}
Code: Select all
if(enemy_vis = false)
{
if(newtarget() = false) // if no other target
{
self.think = LOSTFUNC; // lost sight of enemy
lost_time = time + LOSTTIME;
SetHoldAtEnd(false);
return 0;
}
}
Code: Select all
monster_missile[ ()
{
self.ThinkTime = 0.3;
if(self.health<=0)
{
self.think = "death_biz";
return 0;
}
if((self.in_pain = true) and (random(1,100)<PAINPERCENT))
{
AddExplosion("headshot",GetLastBoneHit(),0,0,0);
}
if(newtargettimer < self.time)
{
newtarget();
newtargettimer = self.time + 2;
}
exist = EnemyExist(DAMAGEATTRIBUTE);
if(exist < 2)
{
SetHoldAtEnd(false);
HighLevel("LostTarget"); // enemy is dead and gone
return 0;
}
if(exist = 2)
{
SetHoldAtEnd(false);
HighLevel("LostTarget"); // enemy is dead but body remains
return 0;
}
if(enemy_vis = false)
{
if(newtarget() = false) // if no other target
{
self.think = LOSTFUNC; // lost sight of enemy
lost_time = time + LOSTTIME;
SetHoldAtEnd(false);
return 0;
}
}
if(self.player_Y>self.current_Y)
{
Animate(SHOOTUP);
AddExplosion(FLASH,"Bip01 R Hand",0,0,0);
FireProjectile(PROJECTILE, FIREBONE, OFFSETX, OFFSETY, OFFSETZ, DAMAGEATTRIBUTE);
PlaySound("shotfire.wav", 500);
SetHoldAtEnd(false);
self.ThinkTime = 0.3;
}
if(self.player_Y<self.current_Y)
{
Animate(SHOOTDOWN);
AddExplosion(FLASH,"FIREBONE",0,0,0);
FireProjectile(PROJECTILE, FIREBONE, OFFSETX, OFFSETY, OFFSETZ, DAMAGEATTRIBUTE);
PlaySound("shotfire.wav", 500);
SetHoldAtEnd(false);
self.ThinkTime = 0.3;
}
if(enemy_range>MISSILERANGE)
{
Animate(MISSILEATTACK);
FireProjectile(PROJECTILE, FIREBONE, OFFSETX, OFFSETY, OFFSETZ, DAMAGEATTRIBUTE);
fire_delay = time + FIREDELAY; // set firing delay
PlaySound("shotfire.wav", 500);
self.think = RUNFUNC; // too far away so run toward
SetHoldAtEnd(false);
return 0;
}
if(skill_time<time) // update according to skill level
{
UpdateTarget(); // update target location
skill_time = time + (SKILL*0);
ai_face(); // face enemy while attacking
}
if(fire_delay<time) // delay after animation starts before firing
{
FireProjectile(PROJECTILE, FIREBONE, OFFSETX, OFFSETY, OFFSETZ, DAMAGEATTRIBUTE);
fire_delay = time + 1000; // set delay well ahead so it is ignored
PlaySound("shotfire.wav", 500);
}
if(self.animate_at_end = true)
{
if(attack_delay < time)
{
//self.think = RUNFUNC; // no
self.think = "monster_missile_start";
SetHoldAtEnd(false);
self.ThinkTime = 0;
}
}
} ]
Note: I haven't actually tested the script so make sure you run it with the console on so you see if there are any syntax errors. I'll try to test it when I have the time.
Pain is only psychological.
- metal_head
- Posts: 1244
- Joined: Sat Jan 05, 2008 8:31 pm
- Location: Bulgaria,Sofia
- Contact:
Re: Attacking Order
wow! it's working! but I noticed a little change in the framerate...hope that's because my computer got slow for the last 6 months (yep,the computer keeps getting slower and slower,no matter what I do,it's not because of viruses )
Re: Attacking Order
How much memory have you?yep,the computer keeps getting slower and slower,no matter what I do,it's not because of viruses
You just installed Vista didn't you? Vista is extremely memory hungry. You need loads more memory for Vista than you needed for XP.
- metal_head
- Posts: 1244
- Joined: Sat Jan 05, 2008 8:31 pm
- Location: Bulgaria,Sofia
- Contact:
Re: Attacking Order
yeah,that also,but when I reinstalled my computer with XP,it was also slow... my cimputer is old now,but I don't think 3.02Ghz ,1 GB ram and 256 MB video card should get that slow.
BTW,I'll search in the internet to see if it's possible to remove all thqat graphical extras comming with Vista,because I Don't need them and they take memory,right?
BTW,I'll search in the internet to see if it's possible to remove all thqat graphical extras comming with Vista,because I Don't need them and they take memory,right?
Re: Attacking Order
Vista need 512mb ram just to sit and Idle doing nothing. You can get by on 1gb but to run games you need at least 2gb ram 4gb would be better.
- metal_head
- Posts: 1244
- Joined: Sat Jan 05, 2008 8:31 pm
- Location: Bulgaria,Sofia
- Contact:
Re: Attacking Order
oh,not cool...I'll buy a new computer soon,but I don't have enogh money now