void widow_attack (edict_t *self) { float luck; qboolean rail_frames = false, blaster_frames = false, blocked = false, anger = false; self->movetarget = NULL; if (self->monsterinfo.aiflags & AI_BLOCKED) { blocked = true; self->monsterinfo.aiflags &= ~AI_BLOCKED; } if (self->monsterinfo.aiflags & AI_TARGET_ANGER) { anger = true; self->monsterinfo.aiflags &= ~AI_TARGET_ANGER; } if ((!self->enemy) || (!self->enemy->inuse)) return; if (self->bad_area) { if ((random() < 0.1) || (level.time < self->timestamp)) self->monsterinfo.currentmove = &widow_move_attack_pre_blaster; else { gi.sound (self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &widow_move_attack_pre_rail; } return; } if ((self->s.frame == FRAME_walk13) || ((self->s.frame >= FRAME_walk01) && (self->s.frame <= FRAME_walk03))) rail_frames = true; if ((self->s.frame >= FRAME_walk09) && (self->s.frame <= FRAME_walk12)) blaster_frames = true; WidowCalcSlots(self); // if we can't see the target, spawn stuff regardless of frame if ((self->monsterinfo.attack_state == AS_BLIND) && (SELF_SLOTS_LEFT >= 2)) { self->monsterinfo.currentmove = &widow_move_spawn; return; } // accept bias towards spawning regardless of frame if (blocked && (SELF_SLOTS_LEFT >= 2)) { self->monsterinfo.currentmove = &widow_move_spawn; return; } if ((realrange(self, self->enemy) > 300) && (!anger) && (random() < 0.5) && (!blocked)) { self->monsterinfo.currentmove = &widow_move_run_attack; return; } if (blaster_frames) { if (SELF_SLOTS_LEFT >= 2) { self->monsterinfo.currentmove = &widow_move_spawn; return; } else if (self->monsterinfo.pausetime + BLASTER_TIME <= level.time) { self->monsterinfo.currentmove = &widow_move_attack_pre_blaster; return; } } if (rail_frames) { if (!(level.time < self->timestamp)) { gi.sound (self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &widow_move_attack_pre_rail; } } if ((rail_frames) || (blaster_frames)) return; luck = random(); if (SELF_SLOTS_LEFT >= 2) { if ((luck <= 0.40) && (self->monsterinfo.pausetime + BLASTER_TIME <= level.time)) self->monsterinfo.currentmove = &widow_move_attack_pre_blaster; else if ((luck <= 0.7) && !(level.time < self->timestamp)) { gi.sound (self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &widow_move_attack_pre_rail; } else self->monsterinfo.currentmove = &widow_move_spawn; } else { if (level.time < self->timestamp) self->monsterinfo.currentmove = &widow_move_attack_pre_blaster; else if ((luck <= 0.50) || (level.time + BLASTER_TIME >= self->monsterinfo.pausetime)) { gi.sound (self, CHAN_WEAPON, sound_rail, 1, ATTN_NORM, 0); self->monsterinfo.currentmove = &widow_move_attack_pre_rail; } else // holdout to blaster self->monsterinfo.currentmove = &widow_move_attack_pre_blaster; } }
/*QUAKED monster_widow (1 .5 0) (-40 -40 0) (40 40 144) Ambush Trigger_Spawn Sight */ void SP_monster_widow (edict_t *self) { if (deathmatch->value) { G_FreeEdict (self); return; } sound_pain1 = gi.soundindex ("widow/bw1pain1.wav"); sound_pain2 = gi.soundindex ("widow/bw1pain2.wav"); sound_pain3 = gi.soundindex ("widow/bw1pain3.wav"); sound_search1 = gi.soundindex ("bosshovr/bhvunqv1.wav"); sound_rail = gi.soundindex ("gladiator/railgun.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex ("models/monsters/blackwidow/tris.md2"); VectorSet (self->mins, -40, -40, 0); VectorSet (self->maxs, 40, 40, 144); self->health = 2000 + 1000*(skill->value); if (coop->value) self->health += 500*(skill->value); self->gib_health = -5000; self->mass = 1500; if (skill->value == 3) { self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; self->monsterinfo.power_armor_power = 500; } self->yaw_speed = 30; self->flags |= FL_IMMUNE_LASER; self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; self->pain = widow_pain; self->die = widow_die; self->monsterinfo.melee = widow_melee; self->monsterinfo.stand = widow_stand; self->monsterinfo.walk = widow_walk; self->monsterinfo.run = widow_run; self->monsterinfo.attack = widow_attack; self->monsterinfo.search = widow_search; self->monsterinfo.checkattack = Widow_CheckAttack; self->monsterinfo.sight = widow_sight; self->monsterinfo.blocked = widow_blocked; gi.linkentity (self); self->monsterinfo.currentmove = &widow_move_stand; self->monsterinfo.scale = MODEL_SCALE; WidowPrecache(); WidowCalcSlots(self); widow_damage_multiplier = 1; walkmonster_start (self); }
/* * QUAKED monster_widow (1 .5 0) (-40 -40 0) (40 40 144) Ambush Trigger_Spawn Sight */ void SP_monster_widow(edict_t *self) { if (!self) { return; } /* ace - monsters spawned with FL_RMONSTER will get converted * * to a random spawn spot for the randomizer system. Class * * and tier will be tallied, origin, angles, spawnflags, etc.. * * will also be recorded. This entity will be freed after. */ /* if (self->flags & FL_RMONSTER) { SP_monster_rspawnspot (self); return; } */ if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain1 = gi.soundindex("widow/bw1pain1.wav"); sound_pain2 = gi.soundindex("widow/bw1pain2.wav"); sound_pain3 = gi.soundindex("widow/bw1pain3.wav"); sound_search1 = gi.soundindex("bosshovr/bhvunqv1.wav"); sound_rail = gi.soundindex("gladiator/railgun.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/blackwidow/tris.md2"); VectorSet(self->mins, -40, -40, 0); VectorSet(self->maxs, 40, 40, 144); self->health = 2000 + 1000 * (skill->value); if (coop->value) { self->health += 500 * (skill->value); } self->gib_health = -5000; self->mass = 1500; if (skill->value == 3) { self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; self->monsterinfo.power_armor_power = 500; } self->yaw_speed = 30; self->flags |= FL_IMMUNE_LASER; self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; self->pain = widow_pain; self->die = widow_die; self->monsterinfo.melee = widow_melee; self->monsterinfo.stand = widow_stand; self->monsterinfo.walk = widow_walk; self->monsterinfo.run = widow_run; self->monsterinfo.attack = widow_attack; self->monsterinfo.search = widow_search; self->monsterinfo.checkattack = Widow_CheckAttack; self->monsterinfo.sight = widow_sight; self->monsterinfo.blocked = widow_blocked; gi.linkentity(self); self->monsterinfo.currentmove = &widow_move_stand; self->monsterinfo.scale = MODEL_SCALE; WidowPrecache(); WidowCalcSlots(self); widow_damage_multiplier = 1; walkmonster_start(self); }
void widow2_attack(edict_t *self) { float range, luck; qboolean blocked = false; if (!self) { return; } if (self->monsterinfo.aiflags & AI_BLOCKED) { blocked = true; self->monsterinfo.aiflags &= ~AI_BLOCKED; } if (!self->enemy) { return; } if (self->bad_area) { if ((random() < 0.75) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &widow2_move_attack_pre_beam; } else { self->monsterinfo.currentmove = &widow2_move_attack_disrupt; } return; } WidowCalcSlots(self); /* if we can't see the target, spawn stuff */ if ((self->monsterinfo.attack_state == AS_BLIND) && (SELF_SLOTS_LEFT >= 2)) { self->monsterinfo.currentmove = &widow2_move_spawn; return; } /* accept bias towards spawning */ if (blocked && (SELF_SLOTS_LEFT >= 2)) { self->monsterinfo.currentmove = &widow2_move_spawn; return; } range = realrange(self, self->enemy); if (range < 600) { luck = random(); if (SELF_SLOTS_LEFT >= 2) { if (luck <= 0.40) { self->monsterinfo.currentmove = &widow2_move_attack_pre_beam; } else if ((luck <= 0.7) && !(level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &widow2_move_attack_disrupt; } else { self->monsterinfo.currentmove = &widow2_move_spawn; } } else { if ((luck <= 0.50) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &widow2_move_attack_pre_beam; } else { self->monsterinfo.currentmove = &widow2_move_attack_disrupt; } } } else { luck = random(); if (SELF_SLOTS_LEFT >= 2) { if (luck < 0.3) { self->monsterinfo.currentmove = &widow2_move_attack_pre_beam; } else if ((luck < 0.65) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &widow2_move_spawn; } else { self->monsterinfo.currentmove = &widow2_move_attack_disrupt; } } else { if ((luck < 0.45) || (level.time < self->monsterinfo.attack_finished)) { self->monsterinfo.currentmove = &widow2_move_attack_pre_beam; } else { self->monsterinfo.currentmove = &widow2_move_attack_disrupt; } } } }
/* * QUAKED monster_widow2 (1 .5 0) (-70 -70 0) (70 70 144) Ambush Trigger_Spawn Sight */ void SP_monster_widow2(edict_t *self) { if (!self) { return; } if (deathmatch->value) { G_FreeEdict(self); return; } sound_pain1 = gi.soundindex("widow/bw2pain1.wav"); sound_pain2 = gi.soundindex("widow/bw2pain2.wav"); sound_pain3 = gi.soundindex("widow/bw2pain3.wav"); sound_death = gi.soundindex("widow/death.wav"); sound_search1 = gi.soundindex("bosshovr/bhvunqv1.wav"); sound_tentacles_retract = gi.soundindex("brain/brnatck3.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; self->s.modelindex = gi.modelindex("models/monsters/blackwidow2/tris.md2"); VectorSet(self->mins, -70, -70, 0); VectorSet(self->maxs, 70, 70, 144); self->health = 2000 + 800 + 1000 * (skill->value); if (coop->value) { self->health += 500 * (skill->value); } self->gib_health = -900; self->mass = 2500; if (skill->value == 3) { self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; self->monsterinfo.power_armor_power = 750; } self->yaw_speed = 30; self->flags |= FL_IMMUNE_LASER; self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; self->pain = widow2_pain; self->die = widow2_die; self->monsterinfo.melee = widow2_melee; self->monsterinfo.stand = widow2_stand; self->monsterinfo.walk = widow2_walk; self->monsterinfo.run = widow2_run; self->monsterinfo.attack = widow2_attack; self->monsterinfo.search = widow2_search; self->monsterinfo.checkattack = Widow2_CheckAttack; gi.linkentity(self); self->monsterinfo.currentmove = &widow2_move_stand; self->monsterinfo.scale = MODEL_SCALE; Widow2Precache(); WidowCalcSlots(self); walkmonster_start(self); }
/*QUAKED monster_widow (1 .5 0) (-40 -40 0) (40 40 144) Ambush Trigger_Spawn Sight GoodGuy */ void SP_monster_widow (edict_t *self) { if (deathmatch->value) { G_FreeEdict (self); return; } sound_pain1 = gi.soundindex ("widow/bw1pain1.wav"); sound_pain2 = gi.soundindex ("widow/bw1pain2.wav"); sound_pain3 = gi.soundindex ("widow/bw1pain3.wav"); sound_search1 = gi.soundindex ("bosshovr/bhvunqv1.wav"); // sound_sight = gi.soundindex ("widow/sight.wav"); sound_rail = gi.soundindex ("gladiator/railgun.wav"); // self->s.sound = gi.soundindex ("bosshovr/bhvengn1.wav"); self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; // Lazarus: special purpose skins if ( self->style ) { PatchMonsterModel("models/monsters/blackwidow/tris.md2"); self->s.skinnum = self->style * 2; // self->style = 0; //clear for custom bloodtype flag } self->s.modelindex = gi.modelindex ("models/monsters/blackwidow/tris.md2"); VectorSet (self->mins, -40, -40, 0); VectorSet (self->maxs, 40, 40, 144); if(!self->health) self->health = 2000 + 1000*(skill->value); if (coop->value) self->health += 500*(skill->value); // self->health = 1; if(!self->gib_health) self->gib_health = -5000; if(!self->mass) self->mass = 1500; /* if (skill->value == 2) { self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; self->monsterinfo.power_armor_power = 250; } else */if (skill->value == 3) { self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; self->monsterinfo.power_armor_power = 500; } self->yaw_speed = 30; self->flags |= FL_IMMUNE_LASER; self->monsterinfo.aiflags |= AI_IGNORE_SHOTS; self->pain = widow_pain; self->die = widow_die; self->monsterinfo.melee = widow_melee; self->monsterinfo.stand = widow_stand; self->monsterinfo.walk = widow_walk; self->monsterinfo.run = widow_run; self->monsterinfo.attack = widow_attack; self->monsterinfo.search = widow_search; self->monsterinfo.checkattack = Widow_CheckAttack; self->monsterinfo.sight = widow_sight; self->monsterinfo.blocked = widow_blocked; if (!self->blood_type) self->blood_type = 3; //sparks and blood // Lazarus if(self->powerarmor) { if (self->powerarmortype == 1) self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; else self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; self->monsterinfo.power_armor_power = self->powerarmor; } self->common_name = "Black Widow"; gi.linkentity (self); self->monsterinfo.currentmove = &widow_move_stand; self->monsterinfo.scale = MODEL_SCALE; WidowPrecache(); WidowCalcSlots(self); widow_damage_multiplier = 1; walkmonster_start (self); }