void Cmd_Decoy_f (edict_t *ent) { if (debuginfo->value) gi.dprintf("DEBUG: %s just called Cmd_Decoy_f()\n", ent->client->pers.netname); if (!V_CanUseAbilities(ent, DECOY, M_DEFAULT_COST, true)) return; if (MirroredEntitiesExist(ent)) { gi.cprintf(ent, PRINT_HIGH, "You already have decoys out!\n"); return; } SpawnDrone(ent, 20, false); }
/* ================= MakronSpawn ================= */ void MakronSpawn (edict_t *self) { vec3_t forward; edict_t *makron; makron = SpawnDrone(self->activator, 33, true); VectorCopy(self->s.origin, makron->s.origin); gi.linkentity(makron); AngleVectors(self->s.angles, forward, NULL, NULL); VectorScale(forward, 400, makron->velocity); makron->velocity[2] = 200; makron->groundentity = NULL; makron->gib_health = 0;// don't leave behind a body makron->monsterinfo.walk(makron); self->think = G_FreeEdict; self->nextthink = level.time + FRAMETIME; }
void inv_defenderspawn_think (edict_t *self) { //int num=G_GetEntityIndex(self); // FOR DEBUGGING ONLY vec3_t start; trace_t tr; edict_t *monster=NULL; //FIXME: this isn't a good enough check if monster is dead or not // did our monster die? if (!G_EntIsAlive(self->enemy)) { if (self->orders == MONSTERSPAWN_STATUS_IDLE) { // wait some time before spawning another monster self->wait = level.time + 30; self->orders = MONSTERSPAWN_STATUS_WORKING; //gi.dprintf("%d: monster died, waiting to build monster...\n", num); } // try to spawn another if ((level.time > self->wait) && (monster = SpawnDrone(self, self->sounds, true)) != NULL) { //gi.dprintf("%d: attempting to spawn a monster\n", num); // get starting position VectorCopy(self->s.origin, start); start[2] = self->absmax[2] + 1 + abs(monster->mins[2]); tr = gi.trace(start, monster->mins, monster->maxs, start, NULL, MASK_SHOT); // kill dead bodies if (tr.ent && tr.ent->takedamage && (tr.ent->deadflag == DEAD_DEAD || tr.ent->health < 1)) T_Damage(tr.ent, self, self, vec3_origin, tr.ent->s.origin, vec3_origin, 10000, 0, 0, 0); // spawn is blocked, try again later else if (tr.fraction < 1) { //gi.dprintf("%d: spawn is blocked, will try again\n", num); G_FreeEdict(monster); self->nextthink = level.time + 1.0; return; } // should this monster stand ground? if (self->style) monster->monsterinfo.aiflags |= AI_STAND_GROUND; monster->s.angles[YAW] = self->s.angles[YAW]; // move the monster onto the spawn pad VectorCopy(start, monster->s.origin); VectorCopy(start, monster->s.old_origin); monster->s.event = EV_OTHER_TELEPORT; // give them quad/invuln to prevent spawn-camping if (self->count) monster->monsterinfo.inv_framenum = level.framenum + self->count; else monster->monsterinfo.inv_framenum = level.framenum + 60; gi.linkentity(monster); self->enemy = monster; // keep track of this monster //gi.dprintf("%d: spawned a monster successfully\n", num); } else { //if (level.time > self->wait) // gi.dprintf("%d: spawndrone() failed to spawn a monster\n", num); //else if (!(level.framenum%10)) // gi.dprintf("%d: waiting...\n", num); } } else { //if (self->orders == MONSTERSPAWN_STATUS_WORKING) // gi.dprintf("%d: spawn is now idle\n", num); self->orders = MONSTERSPAWN_STATUS_IDLE; } self->nextthink = level.time + FRAMETIME; }
edict_t* INV_SpawnDrone(edict_t* self, edict_t *e, int index) { edict_t *monster; vec3_t start; trace_t tr; int mhealth = 1; monster = SpawnDrone(self, index, true); //monster = SpawnDrone(self, 4, true); // calculate starting position VectorCopy(e->s.origin, start); start[2] = e->absmax[2] + 1 + abs(monster->mins[2]); tr = gi.trace(start, monster->mins, monster->maxs, start, NULL, MASK_SHOT); // don't spawn here if a friendly monster occupies this space if (index != 30) // not a boss? if ((tr.fraction < 1) || (tr.ent && tr.ent->inuse && tr.ent->activator && tr.ent->activator->inuse && (tr.ent->activator == self) && (tr.ent->deadflag != DEAD_DEAD))) { // remove the monster and try again M_Remove(monster, false, false); return NULL; } e->wait = level.time + 1.0; // time until spawn is available again monster->monsterinfo.aiflags |= AI_FIND_NAVI; // search for navi monster->s.angles[YAW] = e->s.angles[YAW]; monster->prev_navi = NULL; // we modify the monsters' health lightly if (invasion->value == 1) // easy mode { if (invasion_difficulty_level < 7 && invasion_difficulty_level > 5) mhealth = (invasion_difficulty_level-5) * 0.2 + 1; else if (invasion_difficulty_level >= 7) mhealth = 1.8 + 0.15 * invasion_difficulty_level; }else if (invasion->value == 2) // hard mode { mhealth = 1.63 + 0.22 * invasion_difficulty_level; } monster->max_health = monster->health = monster->max_health*mhealth; // move the monster onto the spawn pad if (index != 30) { VectorCopy(start, monster->s.origin); VectorCopy(start, monster->s.old_origin); } monster->s.event = EV_OTHER_TELEPORT; if (e->count) monster->monsterinfo.inv_framenum = level.framenum + e->count; else { if (invasion->value == 1) monster->monsterinfo.inv_framenum = level.framenum + 60; // give them quad/invuln to prevent spawn-camping else if (invasion->value == 2) monster->monsterinfo.inv_framenum = level.framenum + 80; // Hard mode invin } gi.linkentity(monster); return monster; }