void magmine_think(edict_t *self) { // check for valid position if (gi.pointcontents(self->s.origin) & CONTENTS_SOLID) { gi.dprintf("WARNING: A mag mine was removed from map due to invalid position.\n"); safe_cprintf(self->creator, PRINT_HIGH, "Your mag mine was removed.\n"); self->creator->magmine = NULL; G_FreeEdict(self); return; } if (!self->enemy) { if (magmine_findtarget(self)) { magmine_attack(self); magmine_throwsparks(self); } } else if (G_ValidTarget(self, self->enemy, true) && (entdist(self, self->enemy) <= self->dmg_radius)) { magmine_attack(self); magmine_throwsparks(self); } else { self->enemy = NULL; } //magmine_seteffects(self); M_SetEffects(self);//4.5 self->nextthink = level.time + FRAMETIME; }
void mytank_reattack_blaster (edict_t *self) { float r, range; if (G_ValidTarget(self, self->enemy, true)) { r = random(); range = entdist(self, self->enemy); // medium range = 80% chance to continue attack if (range <= 512) { if (r <= 0.8) self->monsterinfo.currentmove = &mytank_move_reattack_blast; else self->monsterinfo.currentmove = &mytank_move_attack_post_blast; } // long range = 50% chance to continue attack else { if (r <= 0.5) self->monsterinfo.currentmove = &mytank_move_reattack_blast; else self->monsterinfo.currentmove = &mytank_move_attack_post_blast; } } else { self->monsterinfo.currentmove = &mytank_move_attack_post_blast; } // don't call the attack function again for awhile! self->monsterinfo.attack_finished = level.time + 2.0 + random(); }
void gunner_attack (edict_t *self) { float r = random(); float dist = entdist(self, self->enemy); // short range (20% chance grenade, 80% chance run and shoot) if (dist <= 128) { if (r <= 0.2) self->monsterinfo.currentmove = &mygunner_move_attack_grenade; else self->monsterinfo.currentmove = &mygunner_move_runandshoot; } // medium range (100% run and shoot) else if (dist <= 512) { self->monsterinfo.currentmove = &mygunner_move_runandshoot; } // long range (50% chance chaingun) else { if (r <= 0.5) self->monsterinfo.currentmove = &mygunner_move_attack_chain; else self->monsterinfo.attack_finished = level.time + 2.0;// don't attack, try to get closer } }
void chick_fire_attack (edict_t *self) { float r = random(); float range = entdist(self, self->enemy); // medium-long range if (range <= 768) { // 30% chance to cast meteor, 70% chance to shoot fireballs if (r <= 0.3) { self->monsterinfo.currentmove = &mychick_move_slash; } else { if (self->monsterinfo.aiflags & AI_STAND_GROUND) self->monsterinfo.currentmove = &mychick_move_attack1; else mychick_runandshoot(self); } } // long range else self->monsterinfo.currentmove = &mychick_move_slash;// always cast meteor // don't call the attack function again for awhile! self->monsterinfo.attack_finished = level.time + 1; }
void mytank_refire_rocket (edict_t *self) { float r, range; if (G_ValidTarget(self, self->enemy, true)) { r = random(); range = entdist(self, self->enemy); // medium range if (range <= 512) { if (r <= 0.8) self->monsterinfo.currentmove = &mytank_move_attack_fire_rocket; else self->monsterinfo.currentmove = &mytank_move_attack_post_rocket; } // long range else { if (r <= 0.5) self->monsterinfo.currentmove = &mytank_move_attack_fire_rocket; else self->monsterinfo.currentmove = &mytank_move_attack_post_rocket; } } // end attack sequence else { self->monsterinfo.currentmove = &mytank_move_attack_post_rocket; } // don't call the attack function again for awhile! self->monsterinfo.attack_finished = level.time + 2.5 + random(); }
void mytank_chain_refire (edict_t *self) { float r, range; // is enemy still valid? if (G_ValidTarget(self, self->enemy, true)) { r = random(); range = entdist(self, self->enemy); // medium range = 50% chance to continue attack if (range <= 512) { if (r <= 0.5) self->monsterinfo.currentmove = &mytank_move_attack_chain; else self->monsterinfo.currentmove = &mytank_move_attack_chain_end; } // long range = 80% chance to continue attack else if (r <= 0.8) self->monsterinfo.currentmove = &mytank_move_attack_chain; // end attack sequence else self->monsterinfo.currentmove = &mytank_move_attack_chain_end; } else { self->monsterinfo.currentmove = &mytank_move_attack_chain_end; } // don't call the attack function again for awhile! self->monsterinfo.attack_finished = level.time + 2.0 + random(); }
void makron_attack(edict_t *self) { float r, range; r = random(); range = entdist(self, self->enemy); // medium range if (range <= 768) { if (r <= 0.2) self->monsterinfo.currentmove = &makron_move_attack5; // railgun else if (r <= 0.6) self->monsterinfo.currentmove = &makron_move_attack4; // hyperblaster else self->monsterinfo.currentmove = &makron_move_attack3; // bfg } // long range else { if (r <= 0.3) self->monsterinfo.currentmove = &makron_move_attack3; // bfg else self->monsterinfo.currentmove = &makron_move_attack5; // railgun } self->monsterinfo.attack_finished = level.time + GetRandom(1, 3); }
void gunner_stand_attack (edict_t *self) { if (entdist(self, self->enemy) <= 384 && random() <= 0.8) self->monsterinfo.currentmove = &mygunner_move_attack_grenade; else self->monsterinfo.currentmove = &mygunner_move_attack_chain; }
void mymedic_attack(edict_t *self) { float dist, r; if (!self->enemy) return; if (!self->enemy->inuse) return; dist = entdist(self, self->enemy); r = random(); if ((self->monsterinfo.aiflags & AI_MEDIC) && ((self->enemy->health < 1 || OnSameTeam(self, self->enemy)))) { if (dist <= 256) self->monsterinfo.currentmove = &mymedic_move_attackCable; return; } if (dist <= 256) { if (r <= 0.2) self->monsterinfo.currentmove = &mymedic_move_attackHyperBlaster; else self->monsterinfo.currentmove = &mymedic_move_attackBlaster; } else { if (r <= 0.3) self->monsterinfo.currentmove = &mymedic_move_attackBlaster; else self->monsterinfo.currentmove = &mymedic_move_attackHyperBlaster; } }
void commander_attack (edict_t *self) { float r = random(); float range = entdist(self, self->enemy); // short range attack if (range <= 128 && r <= 0.6) { self->monsterinfo.currentmove = &mytank_move_strike; } else { // try to teleport to enemy if we are not standing ground if (!(self->monsterinfo.aiflags & AI_STAND_GROUND)) { if (TeleportNearTarget(self, self->enemy, 16.0)) { if (r <= 0.5) { self->monsterinfo.currentmove = &mytank_move_strike; self->monsterinfo.attack_finished = level.time + 0.5; return; } // recalculate enemy distance range = entdist(self, self->enemy); } } // medium range attack if (range <= 512) { if (r <= 0.2) self->monsterinfo.currentmove = &mytank_move_attack_blast; else self->monsterinfo.currentmove = &mytank_move_attack_fire_rocket; } // long range attack else { self->monsterinfo.currentmove = &mytank_move_attack_blast; } } // don't call attack function for awhile self->monsterinfo.attack_finished = level.time + 2.0; }
static qboolean parasite_cantarget (edict_t *self, edict_t *target) { int para_range = PARASITE_ATTACK_RANGE; return (G_EntExists(target) && !que_typeexists(target->curses, CURSE_FROZEN) && !OnSameTeam(self, target) && visible(self, target) && nearfov(self, target, 45, 45) && (entdist(self, target) <= para_range)); }
void mymedic_cable_continue (edict_t *self) { // if target still needs healing, loop heal frames if (M_ValidMedicTarget(self, self->enemy) && (entdist(self, self->enemy) <= 256)) { self->s.frame = 218; mymedic_cable_attack(self); } }
void m_soldier_attack1_refire1 (edict_t *self) { // continue firing if the enemy is still close, or we are standing ground if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.9) && ((entdist(self, self->enemy) <= 512) || (self->monsterinfo.aiflags & AI_STAND_GROUND))) { self->s.frame = FRAME_attak102; self->monsterinfo.attack_finished = level.time + 2; } }
void mygunner_delay (edict_t *self) { if (!self->enemy || !self->enemy->inuse) return; // delay next attack if we're not standing ground, our enemy isn't within close range // (we need to get closer) and we are not a tank commander/boss if (!(self->monsterinfo.aiflags & AI_STAND_GROUND) && (entdist(self, self->enemy) > 256)) self->monsterinfo.attack_finished = level.time + GetRandom(5, 20)*FRAMETIME; }
void mybrain_melee (edict_t *self) { if (entdist(self, self->enemy) < MELEE_DISTANCE) { if (random() <= 0.5) self->monsterinfo.currentmove = &mybrain_move_attack1; else self->monsterinfo.currentmove = &mybrain_move_attack2; } }
void mygunner_continue (edict_t *self) { if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.9) && (entdist(self, self->enemy) <= 512)) self->monsterinfo.currentmove = &mygunner_move_runandshoot; else self->monsterinfo.currentmove = &mygunnermove_run; // don't call the attack function again for awhile! self->monsterinfo.attack_finished = level.time + 1.0; }
void mymedic_heal (edict_t *self) { // stop healing our target died, if they are fully healed, or // they have gone out of range while we are standing ground (can't reach them) if (!G_EntIsAlive(self->enemy) || !M_NeedRegen(self->enemy) || ((self->monsterinfo.aiflags & AI_STAND_GROUND) && (entdist(self, self->enemy) > 256))) { self->enemy = NULL; mymedic_stand(self); return; } // continue healing if our target is still in range and // there are no enemies around if (OnSameTeam(self, self->enemy) && (entdist(self, self->enemy) <= 256) && !mymedic_findenemy(self)) self->monsterinfo.currentmove = &mymedic_move_attackCable; else mymedic_run(self); }
void gunner_refire_grenade (edict_t *self) { // continue firing unless enemy is no longer valid or out of range if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.8) && (entdist(self, self->enemy) <= 384)) self->monsterinfo.currentmove = &mygunner_move_attack_grenade; else self->monsterinfo.currentmove = &mygunner_move_attack_grenade_end; // don't call the attack function again for awhile! self->monsterinfo.attack_finished = level.time + 0.5; }
void minisentry_pain (edict_t *self, edict_t *other, float kick, int damage) { if (!self->enemy && G_ValidTarget(self, other, true) && (entdist(self, other)<SENTRY_ATTACK_RANGE)) self->enemy = other; if (level.time < self->pain_debounce_time) return; self->pain_debounce_time = level.time + 2; gi.sound (self, CHAN_VOICE, gi.soundindex ("tank/tnkpain2.wav"), 1, ATTN_NORM, 0); }
void m_soldier_runandshoot_continue (edict_t *self) { if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.9) && (entdist(self, self->enemy) <= 512)) { self->monsterinfo.currentmove = &m_soldier_move_runandshoot; self->monsterinfo.attack_finished = level.time + 2; return; } self->monsterinfo.currentmove = &m_soldier_move_run; }
void mymedic_refire (edict_t *self) { if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.5) && (entdist(self, self->enemy) <= 512)) { self->s.frame = FRAME_attack19; return; } self->monsterinfo.currentmove = &mymedic_move_run; self->monsterinfo.attack_finished = level.time + random() + 1; }
void mygunner_refire_chain(edict_t *self) { // keep firing if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.8) && entdist(self, self->enemy) > 128) self->monsterinfo.currentmove = &mygunner_move_fire_chain; else self->monsterinfo.currentmove = &mygunner_move_endfire_chain; //mygunner_delay(self); // don't call the attack function again for awhile! self->monsterinfo.attack_finished = level.time + 0.5; }
void mychick_rerocket(edict_t *self) { if (G_ValidTarget(self, self->enemy, true)) { if (random() <= 0.8 && (entdist(self, self->enemy) <= 512 || (self->monsterinfo.aiflags & AI_STAND_GROUND))) self->monsterinfo.currentmove = &mychick_move_attack1; else self->monsterinfo.currentmove = &mychick_move_end_attack1; } else self->monsterinfo.currentmove = &mychick_move_end_attack1; // don't call the attack function again for awhile! self->monsterinfo.attack_finished = level.time + 0.5; }
void m_soldier_attack (edict_t *self) { if (self->monsterinfo.aiflags & AI_STAND_GROUND) { self->monsterinfo.currentmove = &m_soldier_move_attack1; return; } if ((entdist(self, self->enemy) < 128) && (random() <= 0.8)) self->monsterinfo.currentmove = &m_soldier_move_attack1; else self->monsterinfo.currentmove = &m_soldier_move_runandshoot; self->monsterinfo.attack_finished = level.time + 2; }
void mytank_restrike (edict_t *self) { if (G_ValidTarget(self, self->enemy, true) && (random() <= 0.6 || !self->enemy->client) && (entdist(self, self->enemy) < 128)) { self->monsterinfo.currentmove = &mytank_move_strike; } else { self->monsterinfo.currentmove = &mytank_move_post_strike; } // don't call the attack function again for awhile! self->monsterinfo.attack_finished = level.time + 0.5 + random(); }
void gladiator_cleaver_refire (edict_t *self) { if (self->monsterinfo.bonus_flags & BF_UNIQUE_LIGHTNING) return; if (G_ValidTarget(self, self->enemy, true) && (entdist(self, self->enemy) <= 96) && (random() <= 0.8)) { self->s.frame = 41; gladiator_cleaver_swing(self); return; } self->monsterinfo.melee_finished = level.time + GetRandom(5, 10)*FRAMETIME; }
void mychick_reslash(edict_t *self) { if (self->enemy->health > 0) { if (entdist (self, self->enemy) == 32) if (random() <= 0.9) { self->monsterinfo.currentmove = &mychick_move_slash; return; } else { self->monsterinfo.currentmove = &mychick_move_end_slash; return; } } self->monsterinfo.currentmove = &mychick_move_end_slash; }
void tank_attack (edict_t *self) { float r = random(); float range = entdist(self, self->enemy); //gi.dprintf("%d tank_attack()\n", level.framenum); // short range attack (60% strike, then 20% blaster, 80% rocket) if (range <= 128) { if ((!self->enemy->client || r <= 0.6) && self->groundentity) { self->monsterinfo.currentmove = &mytank_move_strike; } else { if (r <= 0.2) self->monsterinfo.currentmove = &mytank_move_attack_blast; else self->monsterinfo.currentmove = &mytank_move_attack_fire_rocket; } } // medium range attack (20% chain, 40% blaster, 40% rocket) else if (range <= 512) { if (r <= 0.2) self->monsterinfo.currentmove = &mytank_move_attack_chain; else if (r <= 0.6) self->monsterinfo.currentmove = &mytank_move_attack_blast; else self->monsterinfo.currentmove = &mytank_move_attack_fire_rocket; } // long range attack (20% blaster, 80% chain) else { if (r <= 0.2) self->monsterinfo.currentmove = &mytank_move_attack_blast; else self->monsterinfo.currentmove = &mytank_move_attack_chain; } // don't call attack function for awhile self->monsterinfo.attack_finished = level.time + 2.0; }
void CurseRadiusAttack (edict_t *caster, int type, int range, int radius, float duration, qboolean isCurse) { edict_t *e=NULL, *f=NULL; // write a nice effect so everyone knows we've cast a spell gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_TELEPORT_EFFECT); gi.WritePosition (caster->s.origin); gi.multicast (caster->s.origin, MULTICAST_PVS); caster->client->idle_frames = 0; caster->client->ability_delay = level.time;// for monster hearing (check if ability was recently used/cast) // find a target closest to the caster's reticle while ((e = findclosestreticle(e, caster, range)) != NULL) { if (!CanCurseTarget(caster, e, type, isCurse, true)) continue; if (entdist(caster, e) > range) continue; if (!infront(caster, e)) continue; if (!curse_add(e, caster, type, 0, duration)) continue; CurseMessage(caster, e, type, duration, isCurse); // target anything in-range of this entity while ((f = findradius(f, e->s.origin, radius)) != NULL) { if (!CanCurseTarget(caster, f, type, isCurse, false)) continue; if (f == e) continue; if (!visible(e, f)) continue; if (!curse_add(f, caster, type, 0, duration)) continue; CurseMessage(caster, f, type, duration, isCurse); } break; } }
void mybrain_attack (edict_t *self) { float dist; dist = entdist(self, self->enemy); // jump to our enemy if he's close and on even ground if ((dist > 256) && (self->enemy->absmin[2]+18 >= self->absmin[2]) && (self->enemy->absmin[2]-18 <= self->absmin[2]) && !(self->monsterinfo.aiflags & AI_STAND_GROUND)) self->monsterinfo.currentmove = &mybrain_move_jumpattack; // use sucking attack if enemy is within 256 units and can be moved else if ((dist <= 256) && (self->enemy->movetype != MOVETYPE_NONE) && (self->enemy->movetype != MOVETYPE_TOSS)) self->monsterinfo.currentmove = &mybrain_move_attack3; // use melee attack if we're close else if (dist <= MELEE_DISTANCE) mybrain_melee(self); }