super-coop/source/ai_monsters.qc

220 lines
4.8 KiB
Plaintext
Raw Permalink Normal View History

// ai_monsters.qc: basic monster functions
2019-09-11 11:47:16 -07:00
/* ALL MONSTERS SHOULD BE 1 0 0 IN COLOR */
// name =[framenum, nexttime, nextthink] {code}
// expands to:
// name()
// {
// self.frame=framenum;
// self.nextthink = time + nexttime;
// self.think = nextthink
// <code>
// };
float() enemy_is_high = {
return !self.enemy ||
fabs(self.enemy.origin_z - self.origin_z) >= AI_MONSTER_HIGH;
};
2019-09-11 11:47:16 -07:00
/*
================
monster_use
Using a monster makes it angry at the current activator
================
*/
void() monster_use = {
if(self.enemy) {
return;
}
if(self.health <= 0) {
return;
}
if(activator.items & IT_INVISIBILITY) {
return;
}
if(activator.flags & FL_NOTARGET) {
return;
}
if(activator.classname != "player") {
return;
}
// delay reaction so if the monster is teleported, its sound is still
// heard
self.enemy = activator;
self.nextthink = time + 0.1;
2019-09-20 20:24:56 -07:00
self.think = found_target;
2019-09-11 11:47:16 -07:00
};
/*
================
monster_death_use
When a mosnter dies, it fires all of its targets with the current
enemy as activator.
================
*/
void() monster_death_use = {
2019-09-17 08:26:44 -07:00
entity ent, otemp, stemp;
2019-09-11 11:47:16 -07:00
// fall to ground
if(self.flags & FL_FLY) {
self.flags = self.flags - FL_FLY;
}
if(self.flags & FL_SWIM) {
self.flags = self.flags - FL_SWIM;
}
if(!self.target) {
return;
}
activator = self.enemy;
2019-09-20 20:24:56 -07:00
sub_use_targets();
2019-09-11 11:47:16 -07:00
};
//============================================================================
void() walkmonster_start_go = {
2019-09-17 08:26:44 -07:00
string stemp;
entity etemp;
2019-09-11 11:47:16 -07:00
self.origin_z = self.origin_z + 1; // raise off floor a bit
2019-09-20 20:24:56 -07:00
drop_to_floor();
2019-09-11 11:47:16 -07:00
2019-09-20 20:24:56 -07:00
if(!walk_move(0, 0)) {
print_dbg("walkmonster in wall at: ", vtos(self.origin), "\n");
2019-09-11 11:47:16 -07:00
}
self.takedamage = DAMAGE_AIM;
self.ideal_yaw = self.angles * '0 1 0';
if(!self.yaw_speed) {
self.yaw_speed = 20;
}
self.view_ofs = '0 0 25';
self.use = monster_use;
self.flags = self.flags | FL_MONSTER;
if(self.target) {
self.goalentity = self.movetarget = find(world, targetname, self.target);
2019-09-20 20:24:56 -07:00
self.ideal_yaw = vec_yaw(self.goalentity.origin - self.origin);
2019-09-11 11:47:16 -07:00
if(!self.movetarget) {
2019-09-20 20:24:56 -07:00
print_dbg("Monster can't find target at ", vtos(self.origin), "\n");
2019-09-11 11:47:16 -07:00
}
2019-09-20 20:24:56 -07:00
// this used to be an error_obj
2019-09-11 11:47:16 -07:00
if(self.movetarget.classname == "path_corner") {
self.th_walk();
} else {
self.pausetime = 99999999;
}
self.th_stand();
} else {
self.pausetime = 99999999;
self.th_stand();
}
// spread think times so they don't all happen at same time
self.nextthink = time + 0.1 + random() * 0.5;
2019-09-11 11:47:16 -07:00
};
void() walkmonster_start = {
// delay drop to floor to make sure all doors have been spawned
// spread think times so they don't all happen at same time
self.nextthink = time + 0.1 + random() * 0.5;
2019-09-11 11:47:16 -07:00
self.think = walkmonster_start_go;
total_monsters = total_monsters + 1;
};
void() flymonster_start_go = {
self.takedamage = DAMAGE_AIM;
self.ideal_yaw = self.angles * '0 1 0';
if(!self.yaw_speed) {
self.yaw_speed = 10;
}
self.view_ofs = '0 0 25';
self.use = monster_use;
self.flags = self.flags | FL_FLY;
self.flags = self.flags | FL_MONSTER;
2019-09-20 20:24:56 -07:00
if(!walk_move(0, 0)) {
print_dbg("flymonster in wall at: ", vtos(self.origin), "\n");
2019-09-11 11:47:16 -07:00
}
if(self.target) {
self.goalentity = self.movetarget = find(world, targetname, self.target);
if(!self.movetarget) {
2019-09-20 20:24:56 -07:00
print_dbg("Monster can't find target at ", vtos(self.origin), "\n");
2019-09-11 11:47:16 -07:00
}
2019-09-20 20:24:56 -07:00
// this used to be an error_obj
2019-09-11 11:47:16 -07:00
if(self.movetarget.classname == "path_corner") {
self.th_walk();
} else {
self.pausetime = 99999999;
}
self.th_stand();
} else {
self.pausetime = 99999999;
self.th_stand();
}
self.nextthink = time + 0.1 + random() * 0.5;
2019-09-11 11:47:16 -07:00
};
void() flymonster_start = {
// spread think times so they don't all happen at same time
self.flags |= FL_FLY;
self.nextthink = time + 0.1 + random() * 0.5;
2019-09-11 11:47:16 -07:00
self.think = flymonster_start_go;
total_monsters = total_monsters + 1;
};
void() swimmonster_start_go = {
if(deathmatch) {
remove(self);
return;
}
self.takedamage = DAMAGE_AIM;
self.ideal_yaw = self.angles * '0 1 0';
if(!self.yaw_speed) {
self.yaw_speed = 10;
}
self.view_ofs = '0 0 10';
self.use = monster_use;
self.flags = self.flags | FL_SWIM;
self.flags = self.flags | FL_MONSTER;
if(self.target) {
self.goalentity = self.movetarget = find(world, targetname, self.target);
if(!self.movetarget) {
2019-09-20 20:24:56 -07:00
print_dbg("Monster can't find target at ", vtos(self.origin), "\n");
2019-09-11 11:47:16 -07:00
}
2019-09-20 20:24:56 -07:00
// this used to be an error_obj
self.ideal_yaw = vec_yaw(self.goalentity.origin - self.origin);
2019-09-11 11:47:16 -07:00
self.th_walk();
} else {
self.pausetime = 99999999;
self.th_stand();
}
// spread think times so they don't all happen at same time
self.nextthink = time + 0.1 + random() * 0.5;
2019-09-11 11:47:16 -07:00
};
void() swimmonster_start = {
// spread think times so they don't all happen at same time
self.flags |= FL_SWIM;
self.nextthink = time + 0.1 + random() * 0.5;
2019-09-11 11:47:16 -07:00
self.think = swimmonster_start_go;
total_monsters = total_monsters + 1;
};