Hallo Leute!
Ich versuche das "Perfect AI" Script, aus der AUM 31 so zu modifizieren, dass es mit den Tamplates von v6.5 zusammenarbeitet. Also die Gegner meine plBiped01_entity erkennet!

Bis jetzt hänge ich an zwei Stellen fest:
1. Zeile 204 -> mein plBiped01_entity._health__003 ist hier immer 0 obwohl meine Figur eigentlich 100 haben sollte!
2. Zeile 208 -> ich gleube die c_trace Anweisungen funktionieren nicht wie sie sollen!
Ausserdem bekomme ich "invalid array index" Felermeldungen (Zeilen 248,250,251)!

Hat jemand eine Idee, wo der Fehler liegen könnte??
Thanks!

Code:
  
/////////////////////////////////////////////////////////////////////////////////////////////
// copy the files inside this folder inside your gamestudio folder
// open level5.wmp, build it and run it using ai5.wdl
/////////////////////////////////////////////////////////////////////////////////////////////
// Perfect AI is constantly developed by George Pirvu george@acknex.net
// the maximum number of nodes that can be placed in the level is 100
// the maximum number of enemies that can be placed in the level is 100
// the distance between two consecutive nodes should be smaller than 1000 quants
/////////////////////////////////////////////////////////////////////////////////////////////

//string level5_wmb = <level5.wmb>;
//string player_mdl = <hero.mdl>;
string bullet_mdl = <bullet.mdl>;

string temp_str;

/////////////////////////////////////////////////////////////////////////////////////////////



var max_nodes = 100; // maximum number of nodes that can be used in a level
var max_enemies = 50; // maximum number of enemies that is used in a level
var node_id = 0; // stores the numbers associated to the nodes (0...99)
var target_node; // the closest node to the player that can "see" the player

var node_to_player[101]; // distance from the node to the player, up to 100 nodes
var see_player[101]; // sets the corresponding var to 1 if the node can see the player
var nodex[101]; // x coordinates for the nodes
var nodey[101]; // y coordinates for the nodes
var paths[500001]; // stores the elements for all the paths (up to 100 x 100 nodes x 50 points on each path)

var closest_distance = 999999; // will hold the distance from the closest visible node to the player
var index = 0; // used as a counter from 0 to 99
var enemy_id = -1; // stores the numbers associated to the enemies
var dist_to_enemy[10001]; // holds the distance from the enemy to its surrounding nodes (100 enemies * 100 nodes)
var relax = 0; // will be set to 1 as soon as the enemies have killed the player
var paths_filehandle;

var i; // 4 counters with short names to make the code more readable
var j;
var k;
var l;

var temp_var;
var tnode;

/////////////////////////////////////////////////////////////////////////////////////////////

define alert_dist skill5;
define gentle flag1;
define free_to_move skill41;
define _health__003 skill42;
define start_node skill43;
define closest_node skill44;

/////////////////////////////////////////////////////////////////////////////////////////////

sound beep_sound = <beep.wav>;
sound getpath_wav = <getpath.wav>;
sound hit_wav = <hit.wav>;
sound bullet_wav = <bullet.wav>;
sound death_wav = <death.wav>;

/////////////////////////////////////////////////////////////////////////////////////////////

font system_font = <system.pcx>, 10, 12;

/////////////////////////////////////////////////////////////////////////////////////////////

function trace_back();
function follow_path();
function shoot_bullet();
function move_bullet();
function remove_bullet();
function decrease_health();
function enemy_event();

function pathload();


/////////////////////////////////////////////////////////////////////////////////////////////

function pathload()
{
on_d = null;

fps_max = 60; // limit the frame rate to 60 fps
clip_size = 0; // show all the triangles for all the models

paths_filehandle = file_open_read("paths.txt");
if (paths_filehandle == 0) // "paths.txt" doesn't exist, run compute.wdl first!
{
beep; beep; beep; beep; exit; // shut down the engine
}
else
{
k = 0;
while (k < (node_id * node_id * 50)) // a path can have up to 50 points
{
temp = file_var_read (paths_filehandle);
if (temp != 999) // the current path isn't finished yet
{
paths[k] = temp; // fill the big array
}
else // read a "999" separator, start a new path
{
k = (int(k / 50)) * 50 + 49;
}
k += 1;
}
}
// paths[k] looks like this (just an example):
// 1 <- path from 1 to 1, starts with path[0]
// 2 1 <- path from 2 to 1, starts with path[50]
// 3 1 <- path from 3 to 1, starts with path[100]
// 4 1 <- path from 4 to 1, starts with path[150]
// 5 1 <- path from 5 to 1, etc
// 6 3 1 <- path from 6 to 1
// 7 8 1 <- path from 7 to 1
// 8 1 <- path from 8 to 1
// 9 8 1 <- path from 9 to 1
// 10 5 1 <- path from 10 to 1
// .........
while (1)
{
index %= node_id;
index += 1; // limit "index" to 1...node_id in this demo
if ((node_to_player[index] < closest_distance) && (see_player[index] == 1))
// if the distance from this node to the player is smaller than the current distance to the player
// and we are dealing with a node that can see the player
{
closest_distance = node_to_player[index]; // then we have a new winner!
target_node = index; // and the target is given by the current "index" value
tnode = target_node;
}
else // haven't found a new winner?
{
closest_distance = node_to_player[target_node]; // then use the previous winner
}
wait (1);
}
}

action node // use up to 100 nodes in a level
{
my.invisible = on; // comment this line if you want to see the nodes
my.enable_scan = on; // every node is sensitive to scan
my.event = trace_back;
my.skill47 = 1234; // set this weird value for skill47 = I'm a node
my.passable = on; // don't block the player or the enemies
node_id += 1; // get a unique id number (1..100)
my.skill48 = node_id; // and store it in skill48
nodex[my.skill48] = my.x; // store x and y
nodey[my.skill48] = my.y; // for this node
while (plBiped01_entity == null) {wait (1);} // wait until the player is created
while (1)
{
node_to_player[my.skill48] = vec_dist(plBiped01_entity.x, my.x); // store the distance to the player
if (node_to_player[my.skill48] < 500) // if the player has come closer than 500 quants to this node
{
//trace_mode = ignore_me + ignore_models + ignore_passents;
if (c_trace (my.pos, plBiped01_entity.pos, ignore_me|ignore_models|ignore_passents) == 0) // if this node can "see" the player
{
see_player[my.skill48] = 1; // the node can see the player
}
else
{
see_player[my.skill48] = 0; // this node can't see the player
}
}
sleep (0.1); // trace 10 times a second
}
}


// uses alert_dist, gentle
action enemy
{
wait (2); // give the nodes the chance to scan each other at the beginning (not needed, but takes the load off the cpu)
while (plBiped01_entity == null) {wait (1);}
my.push = -2; // enemy's bullets shouldn't hurt other enemies
my.enable_entity = on; // sensitive to other entities
my.enable_impact = on;
my.enable_trigger = on;
my.trigger_range = 200; // trigger the event when the enemies have come closer than 200 quants to each other
my._health__003 = 100;
my.event = enemy_event;
if (my.alert_dist == 0) {my.alert_dist = 100000;} // chase the player immediately if alert_dist = 0
while (vec_dist (plBiped01_entity.x, my.x) > my.alert_dist) // wait until the player has come close enough to the player
{
ent_cycle("stand", my.skill46); // play "stand" frames animation
my.skill46 += 4 * time; // "stand" animation speed
my.skill46 %= 100;
wait (1);
}
var destination_node;
var current_node; // current node on the shortest path
enemy_id += 1; // get a unique id number (0..29)
my.free_to_move = 1; // this enemy hasn't collided with another enemy yet
my.skill48 = enemy_id; // and store it in skill48
my.skill47 = 5678; // I'm an enemy


while ((plBiped01_entity._health__003 > 0) && (my._health__003 > 0)) //HIER STECKT NOCH EIN FEHLER!!!!!!

{
//trace_mode = ignore_me + ignore_models + ignore_passents;
if (c_trace (my.pos, plBiped01_entity.pos, ignore_me|ignore_models|ignore_passents) == 0) // if the enemy can see the player
{
my.skill46 = 0;
shoot_bullet(); // starts shooting at it
while (my.skill46 < 100)
{
ent_cycle("standshoot", my.skill46); // play "shoot" frames animation
my.skill46 += 15 * time; // "shoot" animation speed
wait (1);
}
}
else
{
my.closest_node = 999999; // set the minimum distance from the enemy to its surrounding nodes to a huge value
temp.x = 360; // horizontal scanning angle
temp.y = 360; // vertical scanning angle
temp.z = 1000; // scanning range
scan_entity (my.x, temp); // scan the nodes nearby to get the closest node to the enemy

if (vec_dist (my.x, plBiped01_entity.x) > 1000) // the player is far away? Pretend to "think" before choosing a new path
{
my.skill46 = 0; // get the new path
while (my.skill46 < 100)
{
ent_cycle("alert", my.skill46); // play "alert" frames animation
my.skill46 += 2 * time; // "alert" animation speed
wait (1);
}
}
else
{
wait (2); // needs to wait more than a frame; the enemy scans the nodes during this interval
}
temp_var = my.start_node;
if (my.start_node != target_node)
{
//snd_play (getpath_wav, 100, 0);

current_node = 0;
// the actual path[m,n] starts in paths[(m - 1) * 50 + n] and continues until it encounters a zero
while (paths[(my.start_node - 1) * 50 + (target_node - 1) * node_id * 50 + current_node] != 0) // loop until you encounter the end of the path (a zero)
{
destination_node.x = nodex[paths[(my.start_node - 1) * 50 + (target_node - 1) * node_id * 50 + current_node]]; // get the previously stored coordinates for this node
destination_node.y = nodey[paths[(my.start_node - 1) * 50 + (target_node - 1) * node_id * 50 + current_node]]; // on x and y
destination_node.z = my.z; // use enemy's height for z
while ((vec_dist (destination_node.x, my.x) > 20) && (relax == 0) && (my.free_to_move == 1)) // if the player isn't dead yet
{
vec_set (temp.x, destination_node.x);
vec_sub (temp.x, my.x);
vec_to_angle (my.pan, temp); // turn the enemy towards destination_node
ent_cycle("run", my.skill46); // play "run" frames animation
my.skill46 += 10 * time; // "run" animation speed
my.skill46 %= 100; // loop animation
my.skill1 = 10 * time;
my.skill2 = 0;
my.skill3 = 0;
move_mode = ignore_passable + glide;
result = ent_move(my.skill1, nullvector);
if (result == 0) // got stuck?
{
break; // get out of both while loops, find the path again
}
if (my.gentle == off)
{
if (c_trace (my.pos, plBiped01_entity.pos) == 0) // if the enemy can see the player
{
break; // get out of the while loop (start shooting as soon as you see the player)
}
}
wait (1);
}
current_node += 1;
if (c_trace (my.pos, plBiped01_entity.pos) == 0) // if the enemy can see the player
{
break; // get out of the while loop (don't follow the old path anymore)
}
wait (1);
}
target_node = tnode;
}
}
}
// the player is dead, so switch to "stand" if you are alive
while (my._health__003 > 0)
{
ent_cycle("stand", my.skill46); // play "stand" frames animation
my.skill46 += 4 * time; // "stand" animation speed
my.skill46 %= 100;
wait (1);
}
}


function trace_back()
{
if ((event_type == event_scan) && (you.skill47 == 5678)) // scanned by the enemy
{
my.skill45 = handle(you); // store "you" because trace will destroy it
//trace_mode = ignore_me + ignore_models + ignore_passents;
if (c_trace (my.x, you.x ,ignore_me|ignore_models|ignore_passents) == 0) // if this node can "see" the enemy that scanned it
{
you = ptr_for_handle(my.skill45); // restore the "you" pointer
dist_to_enemy[my.skill48 + max_enemies * you.skill48] = vec_dist (my.x, you.x);
if ((dist_to_enemy[my.skill48 + max_enemies * you.skill48] < you.closest_node) && (dist_to_enemy[my.skill48 + max_enemies * you.skill48] != 0))
{
you.closest_node = dist_to_enemy[my.skill48 + max_enemies * you.skill48];
}
wait (2); // allow the rest of the nodes to change closest_node (if they should change it)
if (dist_to_enemy[my.skill48 + max_enemies * you.skill48] == you.closest_node) // this is the closest node to the enemy?
{
you.start_node = my.skill48;
}
}
else
{
you = ptr_for_handle(my.skill45); // restore the "you" pointer
dist_to_enemy[my.skill48 + max_enemies * you.skill48] = 0;
}
}
}


function follow_path()
{
my.invisible = on;
my.passable = on;
vec_set (temp.x, my.x);
vec_sub (temp.x, you.x);
vec_to_angle (you.pan, temp); // turn the enemy towards the path marker
}


function shoot_bullet()
{
vec_set (temp.x, plBiped01_entity.x);
vec_sub (temp.x, my.x);
vec_to_angle (my.pan, temp); // turn the enemy towards the player
if (plBiped01_entity._health__003 > 0)
{
ent_create (bullet_mdl, my.pos, move_bullet); // create a bullet
}
}


function move_bullet()
{
my.skill47 = 5; // that's an enemy bullet
my.pan = you.pan; // the bullet and the enemy have the same pan angle
my.push = -1; // passes through enemies, hurts the player
my.enable_entity = on; // the bullet is sensitive to other entities
my.enable_impact = on;
my.enable_block = on; // and to level blocks
my.event = remove_bullet;
while (my != null)
{
my.skill1 = 100 * time; // bullet speed
my.skill2 = 0;
my.skill3 = 0;
move_mode = ignore_you + ignore_passable + ignore_push; // ignores the enemy (its creator = you)
ent_move(my.skill1, nullvector);
wait (1);
}
}


function remove_bullet()
{
if ((my.skill47 == 5) && (you.skill47 == 5)) // two enemy bullets have collided?
{
my.passable = on; // one of them becomes passable
}
my.event = null;
ent_playsound (my, hit_wav, 1000);
sleep (0.4);
ent_remove (me);
}


function decrease_health()
{
if (you.skill47 == 5678) // collided with the enemy?
{
my._health__003 = 0; // instant death
}
else // hit by a bullet?
{
my._health__003 -= 1; // loose 1 health point every tick
}
if (my._health__003 <= 0)
{
my.event = null;
snd_play (death_wav, 40, 0);
my.z -= 30; // set a lower height for the player
camera.roll = 30; // and a weird roll angle
}
}


function enemy_event()
{ Beep();Beep();Beep();Beep();

if ((you.skill47 == 5678) && (vec_dist (my.x, plBiped01_entity.x) > vec_dist (you.x, plBiped01_entity.x))) // collided with or "trigger_range"ed another enemy?
{
my.free_to_move = 0;
you.free_to_move = 1;
my.passable = on; // make way for "you"!
sleep (0.2);
my.passable = off;
my.free_to_move = 1;
}
if (you == plBiped01_entity) // collided with the player?
{
my.event = null; // don't react to any other events from now on
plBiped01_entity._health__003 = 0; // kill the player
vec_set (temp.x, plBiped01_entity.x);
vec_sub (temp.x, my.x);
vec_to_angle (my.pan, temp); // turn the enemy towards the player
my.skill46 = 0;
while (my.skill46 < 90)
{
ent_cycle("point", my.skill46); // you should use "stab" or something like that here, all I've got is "point"
my.skill46 += 1 * time; // animation speed
wait (1);
}
relax = 1; // the player is dead, so the enemies can relax now ;)
}
if (you.skill47 == 1) // hit by player's bullet?
{
my._health__003 -= 1; // loose 1 health point every tick
my.alert_dist = 100000; // the enemy must react if it is shot
if (my._health__003 <= 0) // the enemy is dead
{
my.event = null; // doesn't react to other events from now on
my.invisible = on; // disappears
my.passable = on; // and becomes passable
}
}
}


panel ai_pan
{
pos_x = 0;
pos_y = 0;
layer = 10;
digits = 5, 5, 3, system_font, 1, plBiped01_entity._health__003; // display player's health
flags = overlay, refresh, visible;
}





A8-Com-v 8.47.1