qboolean CanAlly (edict_t *ent, edict_t *other, int range) { // you can't ally with yourself if (ent == other) return false; if (!ValidAlly(ent) || !ValidAlly(other)) { //gi.dprintf("no4\n"); return false; } // check for max allies // alianza con la mitad del server activo (vrxchile v1.3) // si uno de los dos tiene una alianza con mas de la mitad de los jugadores activos, no se pueden aliar. if ( ((numAllies(ent) + 1) > ActivePlayers()/2) || ((numAllies(other) + 1) > ActivePlayers()/2) ) return false; // are we already allied? if (IsAlly(ent, other)) return false; // vrxchile v1.3 encourages alliances ASAP. // are we out of range? /*if (range && (entdist(ent, other) > range)) return false;*/ // can we see each other? /*if (range && !visible(ent, other)) return false;*/ // only allow allies that are close in level // FIXME: we should get an average or median player level if there are >1 allies if (abs(ent->myskills.level - other->myskills.level) > ALLY_MAX_LEVEL_DELTA) { //gi.dprintf("no3\n"); return false; } // only allow allies when their level isn't too high, and server has enough players /*if ((ent->myskills.level > AveragePlayerLevel()*1.5) || (other->myskills.level > AveragePlayerLevel()*1.5) || (ActivePlayers() < 6)) { //gi.dprintf("no1\n"); return false; }*/ //4.5 only allow allies if they have the same combat preferences //if (ent->myskills.respawns != other->myskills.respawns) if (!invasion->value && !pvm->value && !ffa->value) // pvp, always allow no matter the preferences. return true; if (((ent->myskills.respawns & HOSTILE_PLAYERS) != (other->myskills.respawns & HOSTILE_PLAYERS)) || ((ent->myskills.respawns & HOSTILE_MONSTERS) != (other->myskills.respawns & HOSTILE_MONSTERS))) { //gi.dprintf("no2\n"); return false; } return true; }
float TimeFormula() { int base = 4*60; int playeramt = ActivePlayers() * 8; int levelamt = invasion_difficulty_level * 7; int cap = 60; int rval = base - playeramt - levelamt; if (invasion->value == 2) // hard mode cap = 50; if (rval < cap) rval = cap; return rval; }
void INV_SpawnMonsters (edict_t *self) { int players, max_monsters; edict_t *e=NULL; PVM_TotalMonsters(self, true); players = max_monsters = total_players(); // there are still monsters alive if ((self->num_monsters_real > 0) && (self->count == MONSTERSPAWN_STATUS_IDLE)) { // if there's nobody playing, remove all monsters if (players < 1) { PVM_RemoveAllMonsters(self); return; // don't spawn any monsters. } if (level.intermissiontime) { if (self->num_monsters_real) PVM_RemoveAllMonsters(self); return; } if (invasion_data.limitframe > level.time) // we still got time? { self->nextthink = level.time + FRAMETIME; return; }else { gi.bprintf(PRINT_HIGH, "Time's up!\n"); if (invasion_data.boss && invasion_data.boss->deadflag != DEAD_DEAD) // out of time for the boss. { G_PrintGreenText(va("You failed to eliminate the commander soon enough!\n")); gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BOSSTPORT); gi.WritePosition (invasion_data.boss->s.origin); gi.multicast (invasion_data.boss->s.origin, MULTICAST_PVS); gi.unlinkentity(invasion_data.boss); G_FreeEdict(invasion_data.boss); invasion_data.boss = NULL; } // increase the difficulty level for the next wave if (invasion->value == 1) invasion_difficulty_level += 1; else invasion_difficulty_level += 2; // Hard mode. invasion_data.printedmessage = 0; gi.sound(&g_edicts[0], CHAN_VOICE, gi.soundindex("misc/tele_up.wav"), 1, ATTN_NONE, 0); } }else // Timeout has happened or all monsters eliminated { self->count = MONSTERSPAWN_STATUS_WORKING; invasion_data.mspawned = self->num_monsters_real; } if (players < 1) { // if there's nobody playing, then wait until some join self->nextthink = level.time + FRAMETIME; return; } switch (invasion_difficulty_level) { case 1: max_monsters = 10; break; case 2: max_monsters = 20; break; case 3: max_monsters = 25; break; case 4: max_monsters = 30; break; case 5: case 6: case 7: case 8: case 9: case 10: max_monsters = 35; break; // vrxcl 3.2b decrease for not saturating the server hard. default: max_monsters = 40; } if (!(invasion_difficulty_level % 5)) { if (invasion->value == 1) max_monsters = 4*(ActivePlayers()-1); else if (invasion->value == 2) max_monsters = 6*(ActivePlayers()-1); } if (!invasion_data.printedmessage) { invasion_data.limitframe = level.time + TimeFormula(); if (invasion_difficulty_level == 1) { if (invasion->value == 1) gi.bprintf(PRINT_HIGH, "The invasion begins!\n"); else gi.bprintf(PRINT_HIGH, "The invasion... begins.\n"); } if (invasion_difficulty_level % 5) gi.bprintf(PRINT_HIGH, "Welcome to level %d. %d monsters incoming!\n", invasion_difficulty_level, max_monsters); else gi.bprintf(PRINT_HIGH, "Welcome to level %d.\n", invasion_difficulty_level, max_monsters); G_PrintGreenText(va("Timelimit: %dm %ds.\n", (int)TimeFormula() / 60, (int)TimeFormula() % 60)); gi.sound(&g_edicts[0], CHAN_VOICE, gi.soundindex("misc/talk1.wav"), 1, ATTN_NONE, 0); BossCheck(e, self); invasion_data.printedmessage = 1; } while ( ((e = INV_GetMonsterSpawn(e)) != NULL) && invasion_data.mspawned < max_monsters) { int randomval = GetRandom(1, 9); if (invasion_difficulty_level % 5 && invasion->value == 1) // nonboss stage? easy mode? { while ( randomval == 5 ) // disallow medics { randomval = GetRandom(1, 8); } } if (!INV_SpawnDrone(self, e, randomval)) continue; else invasion_data.mspawned++; } if (invasion_data.mspawned == max_monsters) { // increase the difficulty level for the next wave invasion_difficulty_level += 1; invasion_data.printedmessage = 0; invasion_data.mspawned = 0; self->count = MONSTERSPAWN_STATUS_IDLE; } self->nextthink = level.time + FRAMETIME; }