From a4ac414c35a2c111e64325fc1e46c49a0185bc00 Mon Sep 17 00:00:00 2001 From: Diego Ahumada Date: Wed, 4 Sep 2024 20:34:29 -0400 Subject: [PATCH] dynamic pvm system --- server/server.cfg | 2 +- src/combat/common/v_misc.c | 975 ++++++++++++++++-------------- src/entities/drone/drone_decoy.c | 2 +- src/entities/drone/drone_makron.c | 2 +- src/entities/drone/drone_misc.c | 45 +- src/entities/g_spawn.c | 27 +- src/g_local.h | 9 +- src/gamemodes/invasion.c | 36 +- src/quake2/g_layout.c | 8 + src/quake2/g_main.c | 1 + src/quake2/g_save.c | 5 +- src/quake2/g_svcmds.c | 10 +- 12 files changed, 597 insertions(+), 525 deletions(-) diff --git a/server/server.cfg b/server/server.cfg index 7d66877..9024ba7 100644 --- a/server/server.cfg +++ b/server/server.cfg @@ -43,7 +43,7 @@ set allies 1 // enable or disable allies // if 1 monster corpses will not gib. // note: set automatically by lua depending on game mode set nolag 0 -set ffa_respawntime 20 +set ffa_respawntime 10 // make yourself an admin with this password. if left blank, you cannot. // az note: the command for this is not enabled. diff --git a/src/combat/common/v_misc.c b/src/combat/common/v_misc.c index 70cbb27..6ea43f7 100644 --- a/src/combat/common/v_misc.c +++ b/src/combat/common/v_misc.c @@ -2,332 +2,377 @@ #include int vrx_get_joined_players() { - edict_t *player; - int i, clients = 0; + edict_t* player; + int i, clients = 0; - for (i = 1; i <= maxclients->value; i++) { - player = &g_edicts[i]; + for (i = 1; i <= maxclients->value; i++) { + player = &g_edicts[i]; - if (!player->inuse) - continue; - if (G_IsSpectator(player)) - continue; - if (player->ai.is_bot) - continue; + if (!player->inuse) + continue; + if (G_IsSpectator(player)) + continue; + if (player->ai.is_bot) + continue; - clients++; - } + clients++; + } - if (clients < 1) - return 0; + if (clients < 1) + return 0; - return clients; + return clients; } int vrx_get_alive_players(void) { - edict_t *player; - int i, clients = 0; - - for (i = 1; i <= maxclients->value; i++) { - player = &g_edicts[i]; - - if (!player->inuse) - continue; - if (G_IsSpectator(player)) - continue; - if (player->myskills.boss) - continue; - if (!G_EntIsAlive(player)) - continue; - if (player->ai.is_bot) - continue; - - clients++; - } - - if (clients < 1) - return 0; - - return clients; + edict_t* player; + int i, clients = 0; + + for (i = 1; i <= maxclients->value; i++) { + player = &g_edicts[i]; + + if (!player->inuse) + continue; + if (G_IsSpectator(player)) + continue; + if (player->myskills.boss) + continue; + if (!G_EntIsAlive(player)) + continue; + if (player->ai.is_bot) + continue; + + clients++; + } + + if (clients < 1) + return 0; + + return clients; } int PvMAveragePlayerLevel(void) { - edict_t *player; - int players = 0, levels = 0, average, i; - - for (i = 1; i <= maxclients->value; i++) { - player = &g_edicts[i]; - - if (!player->inuse) - continue; - if (G_IsSpectator(player)) - continue; - if (player->myskills.boss) - continue; - players++; - levels += player->myskills.level; - } + edict_t* player; + int players = 0, levels = 0, average, i; - if (players < 1) - return 0; - if (levels < 1) - levels = 1; + for (i = 1; i <= maxclients->value; i++) { + player = &g_edicts[i]; + if (!player->inuse) + continue; + if (G_IsSpectator(player)) + continue; + if (player->myskills.boss) + continue; + players++; + levels += player->myskills.level; + } - average = levels / players; + if (players < 1) + return 0; + if (levels < 1) + levels = 1; - if (average < 1) - average = 1; - if (debuginfo->value) - gi.dprintf("DEBUG: PvM Average player level %d\n", average); - return average; -} + average = levels / players; -int AveragePlayerLevel(void) { - edict_t *player; - int players = 0, levels = 0, average, i; - - for (i = 1; i <= maxclients->value; i++) { - player = &g_edicts[i]; - - if (!player->inuse) - continue; - if (G_IsSpectator(player)) - continue; - if (player->myskills.boss) - continue; - - if (player->ai.is_bot) // az: heheh - continue; - - players++; - levels += player->myskills.level; - // gi.dprintf("%s level %d added, total %d\n", player->client->pers.netname, - // player->myskills.level, players); - } - - if (players < 1) - return 0; - if (levels < 1) - levels = 1; + if (average < 1) + average = 1; - average = levels / players; - - if (average < 1) - average = 1; + if (debuginfo->value) + gi.dprintf("DEBUG: PvM Average player level %d\n", average); + return average; +} - /* if (debuginfo->value) - gi.dprintf("DEBUG: Average player level %d\n", average); - */ - return average; +int AveragePlayerLevel(void) { + edict_t* player; + int players = 0, levels = 0, average, i; + + for (i = 1; i <= maxclients->value; i++) { + player = &g_edicts[i]; + + if (!player->inuse) + continue; + if (G_IsSpectator(player)) + continue; + if (player->myskills.boss) + continue; + + if (player->ai.is_bot) // az: heheh + continue; + + players++; + levels += player->myskills.level; + // gi.dprintf("%s level %d added, total %d\n", player->client->pers.netname, + // player->myskills.level, players); + } + + if (players < 1) + return 0; + if (levels < 1) + levels = 1; + + average = levels / players; + + if (average < 1) + average = 1; + + /* if (debuginfo->value) + gi.dprintf("DEBUG: Average player level %d\n", average); + */ + return average; } int PVM_TotalMonsterLevels(edict_t* monster_owner) { - int monsters = 0; - float mult = 1.0; - edict_t* scan = NULL; - - while ((scan = G_Find(scan, FOFS(classname), "drone")) != NULL) - { - // found a live monster that we own - if (G_EntIsAlive(scan) && scan->activator && (scan->activator == monster_owner)) - { - //4.5 monster bonus flags - if (scan->monsterinfo.bonus_flags & BF_UNIQUE_FIRE - || scan->monsterinfo.bonus_flags & BF_UNIQUE_LIGHTNING) - mult = 25; - else if (scan->monsterinfo.bonus_flags & BF_CHAMPION) - mult = 3.0; - else if (scan->monsterinfo.bonus_flags & BF_BERSERKER) - mult = 1.5; - else if (scan->monsterinfo.bonus_flags & BF_POSESSED) - mult = 4.0; - - monsters += scan->monsterinfo.level * scan->monsterinfo.control_cost * mult; - } - } - - return monsters; + int monsters = 0; + float mult = 1.0; + edict_t* scan = NULL; + + while ((scan = G_Find(scan, FOFS(classname), "drone")) != NULL) + { + // found a live monster that we own + if (G_EntIsAlive(scan) && scan->activator && (scan->activator == monster_owner)) + { + //4.5 monster bonus flags + if (scan->monsterinfo.bonus_flags & BF_UNIQUE_FIRE + || scan->monsterinfo.bonus_flags & BF_UNIQUE_LIGHTNING) + mult = 25; + else if (scan->monsterinfo.bonus_flags & BF_CHAMPION) + mult = 3.0; + else if (scan->monsterinfo.bonus_flags & BF_BERSERKER) + mult = 1.5; + else if (scan->monsterinfo.bonus_flags & BF_POSESSED) + mult = 4.0; + + monsters += scan->monsterinfo.level * scan->monsterinfo.control_cost * mult; + } + } + + return monsters; } -int PVM_TotalMonstersValue(edict_t* monster_owner) +int PVM_TotalMonstersValue(edict_t* monster_owner) { - int i = 0; - float mult = 1.0, temp = 0; - edict_t* e = NULL; - - // gets the first monster in the list - e = DroneList_Iterate(); - - while (e) { - // found a live monster that we own - if (G_EntIsAlive(e) && (e->activator == monster_owner)) { - // unique monsters are especially hard - if (e->monsterinfo.bonus_flags & BF_UNIQUE_FIRE - || e->monsterinfo.bonus_flags & BF_UNIQUE_LIGHTNING) - mult = 5.0; - // champion monsters are harder than normal monsters - else if (e->monsterinfo.bonus_flags & BF_CHAMPION) - mult = 3.0; - else if (e->monsterinfo.bonus_flags & BF_BERSERKER) - mult = 1.5; - else if (e->monsterinfo.bonus_flags & BF_POSESSED) - mult = 4.0; - // add this monster's value to the subtotal - temp += e->monsterinfo.level * e->monsterinfo.control_cost * mult; - } - // iterate to the next monster in the list - e = DroneList_Next(e); - } - - return (int)temp; + int i = 0; + float mult = 1.0, temp = 0; + edict_t* e = NULL; + + // gets the first monster in the list + e = DroneList_Iterate(); + + while (e) { + // found a live monster that we own + if (G_EntIsAlive(e) && (e->activator == monster_owner)) { + // unique monsters are especially hard + if (e->monsterinfo.bonus_flags & BF_UNIQUE_FIRE + || e->monsterinfo.bonus_flags & BF_UNIQUE_LIGHTNING) + mult = 5.0; + // champion monsters are harder than normal monsters + else if (e->monsterinfo.bonus_flags & BF_CHAMPION) + mult = 3.0; + else if (e->monsterinfo.bonus_flags & BF_BERSERKER) + mult = 1.5; + else if (e->monsterinfo.bonus_flags & BF_POSESSED) + mult = 4.0; + // add this monster's value to the subtotal + temp += e->monsterinfo.level * e->monsterinfo.control_cost * mult; + } + // iterate to the next monster in the list + e = DroneList_Next(e); + } + + return (int)temp; } int vrx_pvm_update_total_owned_monsters(edict_t *monster_owner, qboolean update) { int i = 0; edict_t *e = NULL; - if (update) { - e = DroneList_Iterate(); - - while (e) { - // found a live monster that we own - if (G_EntIsAlive(e) && (e->activator == monster_owner)) { - i++; - } - e = DroneList_Next(e); - } - monster_owner->num_monsters_real = i; - return monster_owner->num_monsters_real; - } - return monster_owner->num_monsters_real; // will this work? + if (update) { + e = DroneList_Iterate(); + + while (e) { + // found a live monster that we own + if (G_EntIsAlive(e) && (e->activator == monster_owner)) { + i++; + } + e = DroneList_Next(e); + } + monster_owner->num_monsters_real = i; + return monster_owner->num_monsters_real; + } + return monster_owner->num_monsters_real; // will this work? } int vrx_remove_all_monsters(edict_t *monster_owner) { int i = 0; edict_t *e = NULL; - e = DroneList_Iterate(); + e = DroneList_Iterate(); - while (e) { - if (G_EntExists(e) && e->activator && (e->activator == monster_owner)) { - M_Remove(e, false, false); - i++; - } - e = DroneList_Next(e); - } - return i; + while (e) { + if (G_EntExists(e) && e->activator && (e->activator == monster_owner)) { + M_Remove(e, false, false); + i++; + } + e = DroneList_Next(e); + } + return i; } -//qboolean SpawnWorldMonster(edict_t *ent, int mtype); -void FindMonsterSpot(edict_t *self) { - edict_t *scan = NULL; - int players = vrx_get_joined_players(); - int total_monsters, max_monsters = 0; - int mtype = 0, num = 0, i = 0; - total_monsters = vrx_pvm_update_total_owned_monsters(self, false); - - max_monsters = level.r_monsters; - - // dm_monsters cvar sets the default number of monsters in a given map - if (max_monsters <= 0) - max_monsters = dm_monsters->value; - - if (level.time > self->delay) { - total_monsters = vrx_pvm_update_total_owned_monsters(self, true); - // adjust spawning delay based on efficiency of player monster kills - if (total_monsters < max_monsters) { - if (total_monsters < 0.5 * max_monsters) { - self->random -= 1.0; - - // minimum delay - if (self->random < 5.0) - self->random = 5.0; - } else { - self->random += 1.0; - - // maximum delay - if (self->random > ffa_respawntime->value) - self->random = ffa_respawntime->value; - } - } - - // spawn monsters until we reach the limit - while (total_monsters < max_monsters) { - int rnd; - do { - rnd = GetRandom(1, 15); // az: don't spawn soldiers - } while (rnd == 10); - - if ((scan = vrx_create_new_drone(self, rnd, true, true)) != NULL) { - if (scan->monsterinfo.walk && random() > 0.5) - scan->monsterinfo.walk(scan); - total_monsters++; - } - } - - WriteServerMsg(va("World has %d/%d monsters. Next update in %.1f seconds.", total_monsters, max_monsters, - self->random), "Info", true, false); - - // wait awhile before trying to spawn monsters again - self->delay = level.time + self->random; - } - - // there is a 10-20% chance that a boss will spawn - // if the server is more than 1/6 full - - if (!BossExists() && (self->num_sentries < 1) && (players > 0.6 * maxclients->value)) { - int chance = 10; - - if (ffa->value) - chance *= 2; +void vrx_pvm_spawn_monsters(edict_t* self, int max_monsters, int total_monsters) +{ + int max_spawn_this_cycle = GetRandom(0, max_monsters - total_monsters); + + if (self->count == 0) // first time + max_spawn_this_cycle = max_monsters; + else + max_spawn_this_cycle = max(max_spawn_this_cycle, 3); + + while (total_monsters < max_monsters && max_spawn_this_cycle > 0) { + int rnd; + do { + rnd = GetRandom(1, 14); // az: don't spawn soldiers + } while (rnd == 10); + + edict_t* scan; + if ((scan = vrx_create_new_drone(self, rnd, true, true, self->monsterinfo.scale)) != NULL) { + if (scan->monsterinfo.walk && random() > 0.5) + scan->monsterinfo.walk(scan); + total_monsters++; + max_spawn_this_cycle--; + self->count++; + } + } +} - if (GetRandom(1, 200) <= chance) // oh yeah! - CreateRandomPlayerBoss(true); - } +void vrx_pvm_try_spawn_boss(edict_t* self, int players) +{ + if (!BossExists() && (self->num_sentries < 1) && (players > 0.6 * maxclients->value)) { + int chance = 10; + if (ffa->value) + chance *= 2; - self->nextthink = level.time + FRAMETIME; + if (GetRandom(1, 200) <= chance) // oh yeah! + CreateRandomPlayerBoss(true); + } } -void SpawnRandomBoss(edict_t *self) { - // 3% chance for a boss to spawn a boss if there isn't already one spawned - if (!SPREE_WAR && vrx_get_alive_players() >= 8 && self->num_sentries < 1) { - int chance = GetRandom(1, 100); - - if ((chance >= 97) && vrx_create_new_drone(self, GetRandom(30, 31), true, true)) { - //gi.dprintf("Spawning a boss monster (chance = %d) at %.1f. Waiting 300 seconds to try again.\n", - // chance, level.time); - // 5 minutes until we can try to spawn another boss - self->nextthink = level.time + 300.0; - return; - } - } +//qboolean SpawnWorldMonster(edict_t *ent, int mtype); +void vrx_pvm_spawn_world_monsters(edict_t* self) { + int players = vrx_get_joined_players(); + total_monsters = vrx_pvm_update_total_owned_monsters(self, false); + + // dm_monsters cvar sets the default number of monsters in a given map + int max_monsters = level.r_monsters; + if (level.r_monsters <= 0) + max_monsters = dm_monsters->value; + + int threshold = 0.66f * max_monsters; + int levelup_threshold = 0.4f * max_monsters; + + + + if (level.time > self->delay) { + int total_monsters = vrx_pvm_update_total_owned_monsters(self, true); + // adjust spawning delay based on efficiency of player monster kills + if (total_monsters < max_monsters) { + // if a minimum of monsters has been killed consider scaling monsters up + if (total_monsters < threshold) { + // WriteServerMsg(va("** %d monsters remain **", total_monsters), "Info", true, false); + + // if the players are too efficient then level monsters up + if (total_monsters <= levelup_threshold && self->last_move_time < level.time && self->count) { + self->monsterinfo.scale += max(1, self->monsterinfo.scale); + self->last_move_time = level.time + 15.0; + } + + // reduce delay between monster spawning + self->random *= 0.8; + + // minimum delay + if (self->random < 3.0) + self->random = 3.0; + } else { + // if not enough monsters have been killed scale down + // decrease spawn frequency + self->random += 1.0; + + // scale monster level down + if (self->last_move_time < level.time && self->monsterinfo.scale > 0) { + self->monsterinfo.scale *= 0.7f; + self->last_move_time = level.time + 15.0; + } + + // maximum delay + if (self->random > ffa_respawntime->value) + self->random = ffa_respawntime->value; + } + } + + // spawn monsters until we reach the limit + if (total_monsters < max_monsters) { + vrx_pvm_spawn_monsters(self, max_monsters, total_monsters); + } + + WriteServerMsg(va("World has %d/%d monsters. Next update in %.1f seconds. levelup threshold: %d", + total_monsters, max_monsters, + self->random, levelup_threshold), "Info", true, false); + + // wait awhile before trying to spawn monsters again + self->delay = level.time + self->random; + } + + // there is a 10-20% chance that a boss will spawn + // if the server is more than 1/6 full + + vrx_pvm_try_spawn_boss(self, players); + + level.pvm.level_bonus = self->monsterinfo.scale; + level.pvm.time_to_next_respawn = self->delay - level.time; + self->nextthink = level.time + FRAMETIME; +} - self->nextthink = level.time + 60.0;// try again in 1 minute +void SpawnRandomBoss(edict_t* self) { + // 3% chance for a boss to spawn a boss if there isn't already one spawned + if (!SPREE_WAR && vrx_get_alive_players() >= 8 && self->num_sentries < 1) { + int chance = GetRandom(1, 100); + + if ((chance >= 97) && vrx_create_new_drone(self, GetRandom(30, 31), true, true, 0)) { + //gi.dprintf("Spawning a boss monster (chance = %d) at %.1f. Waiting 300 seconds to try again.\n", + // chance, level.time); + // 5 minutes until we can try to spawn another boss + self->nextthink = level.time + 300.0; + return; + } + } + + self->nextthink = level.time + 60.0;// try again in 1 minute } edict_t *InitMonsterEntity(qboolean manual_spawn) { edict_t *monster; - if (ctf->value || domination->value || ptr->value || tbi->value || trading->value || V_IsPVP()) - return NULL;//4.4 + if (ctf->value || domination->value || ptr->value || tbi->value || trading->value || V_IsPVP()) + return NULL;//4.4 - //if (!pvm->value && !ffa->value) - // return NULL; + //if (!pvm->value && !ffa->value) + // return NULL; - monster = G_Spawn(); + monster = G_Spawn(); - if (manual_spawn) - monster->style = 1; + if (manual_spawn) + monster->style = 1; - monster->classname = "MonsterSpawn"; - monster->svflags |= SVF_NOCLIENT; - monster->mtype = M_WORLDSPAWN; - monster->num_monsters_real = 0; + monster->classname = "MonsterSpawn"; + monster->svflags |= SVF_NOCLIENT; + monster->mtype = M_WORLDSPAWN; + monster->num_monsters_real = 0; + monster->monsterinfo.level = 0; + monster->last_move_time = level.time; /*if (V_IsPVP()) monster->think = SpawnRandomBoss;//4.4 @@ -337,13 +382,13 @@ edict_t *InitMonsterEntity(qboolean manual_spawn) { monster->think = INV_SpawnMonsters; monster->notify_drone_death = INV_NotifyMonsterDeath; } else - monster->think = FindMonsterSpot; + monster->think = vrx_pvm_spawn_world_monsters; - monster->nextthink = pregame_time->value + FRAMETIME; - monster->random = ffa_respawntime->value;//4.52 default delay to begin respawning monsters - gi.linkentity(monster); + monster->nextthink = pregame_time->value + FRAMETIME; + monster->random = ffa_respawntime->value;//4.52 default delay to begin respawning monsters + gi.linkentity(monster); - return monster; + return monster; } /* @@ -356,158 +401,158 @@ Removes all edicts that the player owns void RemoveMagmines(edict_t* ent); -void RemoveProxyGrenades(edict_t *ent); +void RemoveProxyGrenades(edict_t* ent); -void RemoveNapalmGrenades(edict_t *ent); +void RemoveNapalmGrenades(edict_t* ent); -void sentrygun_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point); +void sentrygun_die(edict_t* self, edict_t* inflictor, edict_t* attacker, int damage, vec3_t point); -void RemoveExplodingArmor(edict_t *ent); +void RemoveExplodingArmor(edict_t* ent); void RemoveExplodingBarrels(edict_t* ent, qboolean refund); -void RemoveAutoCannons(edict_t *ent); - -void caltrops_removeall(edict_t *ent); - -void spikegren_removeall(edict_t *ent); - -void detector_removeall(edict_t *ent); - -void minisentry_remove(edict_t *self); - -void organ_remove(edict_t *self, qboolean refund); - -void organ_removeall(edict_t *self, char *classname, qboolean refund); - -void RemoveMiniSentries(edict_t *ent); - -void RemoveAllLaserPlatforms(edict_t *ent);//4.5 -void holyground_remove(edict_t *ent, edict_t *self); - -void depot_remove(edict_t *self, edict_t *owner, qboolean effect); - -void lasertrap_removeall(edict_t *ent, qboolean effect); - -void vrx_remove_player_summonables(edict_t *self) { - edict_t *from; - - // gi.dprintf("vrx_remove_player_summonables()\n"); - - lasertrap_removeall(self, true); - holyground_remove(self, self->holyground); - detector_removeall(self); - caltrops_removeall(self); - organ_removeall(self, "box", false); - organ_removeall(self, "fmedi", false); - organ_removeall(self, "gasser", false); - organ_removeall(self, "obstacle", false); - organ_removeall(self, "spiker", false); - organ_removeall(self, "spikeball", false); - organ_remove(self->healer, false); - organ_remove(self->cocoon, false); - spikegren_removeall(self); - RemoveTotem(self->totem1); - RemoveTotem(self->totem2); - AuraRemove(self, 0); - RemoveLasers(self); - RemoveProxyGrenades(self); - RemoveMagmines(self); - RemoveNapalmGrenades(self); - RemoveExplodingArmor(self); - RemoveExplodingBarrels(self, false); - RemoveAutoCannons(self); - RemoveMiniSentries(self); - RemoveAllLaserPlatforms(self); - - // scan for edicts that we own - for (from = g_edicts; from < &g_edicts[globals.num_edicts]; from++) { - edict_t *cl_ent; - - if (!from->inuse) - continue; - // remove sentry - if ((from->creator) && (from->creator == self) - && !Q_stricmp(from->classname, "Sentry_Gun") && !RestorePreviousOwner(from)) { - sentrygun_die(from, NULL, from->creator, from->health, from->s.origin); - continue; - } - - // remove monsters - if ((from->activator) && (from->activator == self) - && !Q_stricmp(from->classname, "drone") && !RestorePreviousOwner(from)) { - DroneRemoveSelected(self, from); - M_Remove(from, false, true); - self->num_monsters = 0; - self->num_monsters_real = 0; - continue; - } - - // remove force wall - if ((from->activator) && (from->activator == self) - && !Q_stricmp(from->classname, "Forcewall")) { - from->think = BecomeTE; - from->takedamage = DAMAGE_NO; - from->deadflag = DEAD_DEAD; - from->nextthink = level.time + FRAMETIME; - continue; - } - - // remove grenades - if ((from->owner) && (from->owner == self) - && !Q_stricmp(from->classname, "grenade")) { - self->max_pipes = 0; - G_FreeEdict(from); - continue; - } - - // remove bolts - if ((from->owner) && (from->owner == self) - && !Q_stricmp(from->classname, "bolt")) { - G_FreeEdict(from); - } - - // remove hammers - cl_ent = G_GetClient(from); - if (cl_ent && cl_ent->inuse && cl_ent == self - && !Q_stricmp(from->classname, "hammer")) { - self->num_hammers = 0; - G_FreeEdict(from); - continue; - } - } - // remove everything else - if (self->lasersight) { - G_FreeEdict(self->lasersight); - self->lasersight = NULL; - } - if (self->flashlight) { - G_FreeEdict(self->flashlight); - self->flashlight = NULL; - } - - if (self->supplystation) { - depot_remove(self->supplystation, self, true); - } - if (self->skull && !RestorePreviousOwner(self->skull)) { - //BecomeExplosion1(self->skull); - self->skull->think = BecomeExplosion1; - self->skull->takedamage = DAMAGE_NO; - self->skull->deadflag = DEAD_DEAD; - self->skull->nextthink = level.time + FRAMETIME; - self->skull = NULL; - } - if (self->spirit) { - self->spirit->think = G_FreeEdict; - self->spirit->deadflag = DEAD_DEAD; - self->spirit->nextthink = level.time + FRAMETIME; - self->spirit = NULL; - } - hook_reset(self->client->hook); +void RemoveAutoCannons(edict_t* ent); + +void caltrops_removeall(edict_t* ent); + +void spikegren_removeall(edict_t* ent); + +void detector_removeall(edict_t* ent); + +void minisentry_remove(edict_t* self); + +void organ_remove(edict_t* self, qboolean refund); + +void organ_removeall(edict_t* self, char* classname, qboolean refund); + +void RemoveMiniSentries(edict_t* ent); + +void RemoveAllLaserPlatforms(edict_t* ent);//4.5 +void holyground_remove(edict_t* ent, edict_t* self); + +void depot_remove(edict_t* self, edict_t* owner, qboolean effect); + +void lasertrap_removeall(edict_t* ent, qboolean effect); + +void vrx_remove_player_summonables(edict_t* self) { + edict_t* from; + + // gi.dprintf("vrx_remove_player_summonables()\n"); + + lasertrap_removeall(self, true); + holyground_remove(self, self->holyground); + detector_removeall(self); + caltrops_removeall(self); + organ_removeall(self, "box", false); + organ_removeall(self, "fmedi", false); + organ_removeall(self, "gasser", false); + organ_removeall(self, "obstacle", false); + organ_removeall(self, "spiker", false); + organ_removeall(self, "spikeball", false); + organ_remove(self->healer, false); + organ_remove(self->cocoon, false); + spikegren_removeall(self); + RemoveTotem(self->totem1); + RemoveTotem(self->totem2); + AuraRemove(self, 0); + RemoveLasers(self); + RemoveProxyGrenades(self); + RemoveMagmines(self); + RemoveNapalmGrenades(self); + RemoveExplodingArmor(self); + RemoveExplodingBarrels(self, false); + RemoveAutoCannons(self); + RemoveMiniSentries(self); + RemoveAllLaserPlatforms(self); + + // scan for edicts that we own + for (from = g_edicts; from < &g_edicts[globals.num_edicts]; from++) { + edict_t* cl_ent; + + if (!from->inuse) + continue; + // remove sentry + if ((from->creator) && (from->creator == self) + && !Q_stricmp(from->classname, "Sentry_Gun") && !RestorePreviousOwner(from)) { + sentrygun_die(from, NULL, from->creator, from->health, from->s.origin); + continue; + } + + // remove monsters + if ((from->activator) && (from->activator == self) + && !Q_stricmp(from->classname, "drone") && !RestorePreviousOwner(from)) { + DroneRemoveSelected(self, from); + M_Remove(from, false, true); + self->num_monsters = 0; + self->num_monsters_real = 0; + continue; + } + + // remove force wall + if ((from->activator) && (from->activator == self) + && !Q_stricmp(from->classname, "Forcewall")) { + from->think = BecomeTE; + from->takedamage = DAMAGE_NO; + from->deadflag = DEAD_DEAD; + from->nextthink = level.time + FRAMETIME; + continue; + } + + // remove grenades + if ((from->owner) && (from->owner == self) + && !Q_stricmp(from->classname, "grenade")) { + self->max_pipes = 0; + G_FreeEdict(from); + continue; + } + + // remove bolts + if ((from->owner) && (from->owner == self) + && !Q_stricmp(from->classname, "bolt")) { + G_FreeEdict(from); + } + + // remove hammers + cl_ent = G_GetClient(from); + if (cl_ent && cl_ent->inuse && cl_ent == self + && !Q_stricmp(from->classname, "hammer")) { + self->num_hammers = 0; + G_FreeEdict(from); + continue; + } + } + // remove everything else + if (self->lasersight) { + G_FreeEdict(self->lasersight); + self->lasersight = NULL; + } + if (self->flashlight) { + G_FreeEdict(self->flashlight); + self->flashlight = NULL; + } + + if (self->supplystation) { + depot_remove(self->supplystation, self, true); + } + if (self->skull && !RestorePreviousOwner(self->skull)) { + //BecomeExplosion1(self->skull); + self->skull->think = BecomeExplosion1; + self->skull->takedamage = DAMAGE_NO; + self->skull->deadflag = DEAD_DEAD; + self->skull->nextthink = level.time + FRAMETIME; + self->skull = NULL; + } + if (self->spirit) { + self->spirit->think = G_FreeEdict; + self->spirit->deadflag = DEAD_DEAD; + self->spirit->nextthink = level.time + FRAMETIME; + self->spirit = NULL; + } + hook_reset(self->client->hook); } int vrx_GetMonsterCost(int mtype) { - int cost; + int cost; switch (mtype) { case M_FLYER: @@ -563,7 +608,7 @@ int vrx_GetMonsterCost(int mtype) { } int vrx_GetMonsterControlCost(int mtype) { - int cost; + int cost; switch (mtype) { case M_FLYER: @@ -620,59 +665,59 @@ int vrx_GetMonsterControlCost(int mtype) { void shrapnel_touch(edict_t* self, edict_t* other, cplane_t* plane, csurface_t* surf) { - if ((surf && (surf->flags & SURF_SKY)) || !self->creator || !self->creator->inuse) - { - G_FreeEdict(self); - return; - } - - if (other->takedamage) - { - T_Damage(other, self, self->creator, self->velocity, self->s.origin, plane->normal, self->dmg, 0, 0, self->style); - - gi.sound(other, CHAN_WEAPON, gi.soundindex("misc/fhit3.wav"), 1, ATTN_NORM, 0); - G_FreeEdict(self); - } + if ((surf && (surf->flags & SURF_SKY)) || !self->creator || !self->creator->inuse) + { + G_FreeEdict(self); + return; + } + + if (other->takedamage) + { + T_Damage(other, self, self->creator, self->velocity, self->s.origin, plane->normal, self->dmg, 0, 0, self->style); + + gi.sound(other, CHAN_WEAPON, gi.soundindex("misc/fhit3.wav"), 1, ATTN_NORM, 0); + G_FreeEdict(self); + } } void shrapnel_die(edict_t* self, edict_t* inflictor, edict_t* attacker, int damage, vec3_t point) { - G_FreeEdict(self); + G_FreeEdict(self); } void ThrowShrapnel(edict_t* self, char* modelname, float speed, vec3_t origin, int dmg, int mod) { - edict_t* cl, *chunk; - vec3_t v; - - chunk = G_Spawn(); - VectorCopy(origin, chunk->s.origin); - gi.setmodel(chunk, modelname); - v[0] = 100 * crandom(); - v[1] = 100 * crandom(); - v[2] = 100 + 150 * random(); - VectorMA(self->velocity, speed, v, chunk->velocity); - VectorSet(chunk->mins, -4, -4, -2); - VectorSet(chunk->maxs, 4, 4, 2); - chunk->movetype = MOVETYPE_BOUNCE; - chunk->solid = SOLID_BBOX; - chunk->clipmask = MASK_SHOT; - chunk->avelocity[0] = random() * 600; - chunk->avelocity[1] = random() * 600; - chunk->avelocity[2] = random() * 600; - chunk->think = G_FreeEdict; - chunk->nextthink = level.time + 5 + random() * 5; - chunk->s.frame = 0; - chunk->flags = 0; - chunk->classname = "shrapnel"; - //chunk->takedamage = DAMAGE_YES; - chunk->dmg = dmg; - chunk->die = shrapnel_die; - chunk->touch = shrapnel_touch; - chunk->style = mod; // means-of-death - if (cl = G_GetClient(self)) - chunk->creator = cl; // owner-creator of shrapnel - else - chunk->creator = self; - gi.linkentity(chunk); + edict_t* cl, * chunk; + vec3_t v; + + chunk = G_Spawn(); + VectorCopy(origin, chunk->s.origin); + gi.setmodel(chunk, modelname); + v[0] = 100 * crandom(); + v[1] = 100 * crandom(); + v[2] = 100 + 150 * random(); + VectorMA(self->velocity, speed, v, chunk->velocity); + VectorSet(chunk->mins, -4, -4, -2); + VectorSet(chunk->maxs, 4, 4, 2); + chunk->movetype = MOVETYPE_BOUNCE; + chunk->solid = SOLID_BBOX; + chunk->clipmask = MASK_SHOT; + chunk->avelocity[0] = random() * 600; + chunk->avelocity[1] = random() * 600; + chunk->avelocity[2] = random() * 600; + chunk->think = G_FreeEdict; + chunk->nextthink = level.time + 5 + random() * 5; + chunk->s.frame = 0; + chunk->flags = 0; + chunk->classname = "shrapnel"; + //chunk->takedamage = DAMAGE_YES; + chunk->dmg = dmg; + chunk->die = shrapnel_die; + chunk->touch = shrapnel_touch; + chunk->style = mod; // means-of-death + if (cl = G_GetClient(self)) + chunk->creator = cl; // owner-creator of shrapnel + else + chunk->creator = self; + gi.linkentity(chunk); } diff --git a/src/entities/drone/drone_decoy.c b/src/entities/drone/drone_decoy.c index e45f6b9..a195296 100644 --- a/src/entities/drone/drone_decoy.c +++ b/src/entities/drone/drone_decoy.c @@ -544,7 +544,7 @@ void Cmd_Decoy_f (edict_t *ent) return; } - ret = vrx_create_new_drone(ent, 20, false, true); + ret = vrx_create_new_drone(ent, 20, false, true, 0); if (ret) { ret->health_cache += (int)(0.50 * ret->max_health) + 1; diff --git a/src/entities/drone/drone_makron.c b/src/entities/drone/drone_makron.c index 56ef2fd..69c9e3c 100644 --- a/src/entities/drone/drone_makron.c +++ b/src/entities/drone/drone_makron.c @@ -667,7 +667,7 @@ void MakronSpawn (edict_t *self) vec3_t forward; edict_t *makron; - makron = vrx_create_new_drone(self->activator, 33, true, true); + makron = vrx_create_new_drone(self->activator, 33, true, true, 0); VectorCopy(self->s.origin, makron->s.origin); gi.linkentity(makron); diff --git a/src/entities/drone/drone_misc.c b/src/entities/drone/drone_misc.c index 252565e..b46da88 100644 --- a/src/entities/drone/drone_misc.c +++ b/src/entities/drone/drone_misc.c @@ -724,7 +724,7 @@ void vrx_roll_to_make_champion(edict_t *drone, int *drone_type) } } -edict_t *vrx_create_drone_from_ent(edict_t *drone, edict_t *ent, int drone_type, qboolean worldspawn, qboolean link_now) +edict_t *vrx_create_drone_from_ent(edict_t *drone, edict_t *ent, int drone_type, qboolean worldspawn, qboolean link_now, int bonus_level) { vec3_t forward, right, start, end, offset; trace_t tr; @@ -741,7 +741,7 @@ edict_t *vrx_create_drone_from_ent(edict_t *drone, edict_t *ent, int drone_type, else if (INVASION_OTHERSPAWNS_REMOVED) { if (invasion->value == 1) - drone->monsterinfo.level = GetRandom(LowestLevelPlayer(), HighestLevelPlayer())/*+invasion_difficulty_level-1*/; + drone->monsterinfo.level = GetRandom(LowestLevelPlayer(), HighestLevelPlayer()); else if (invasion->value == 2) // hard mode invasion { drone->monsterinfo.level = HighestLevelPlayer()+invasion_difficulty_level-1; @@ -755,12 +755,7 @@ edict_t *vrx_create_drone_from_ent(edict_t *drone, edict_t *ent, int drone_type, else drone->monsterinfo.level = GetRandom(LowestLevelPlayer(), HighestLevelPlayer()); - if (pvm->value) // In PvM mode... Make them tougher. - { - drone->health *= 1.5; - drone->max_health *= 1.5; - } - + drone->monsterinfo.level += bonus_level; // 4.5 assign monster bonus flags // Champions spawn on invasion hard mode. @@ -1007,9 +1002,9 @@ edict_t *vrx_create_drone_from_ent(edict_t *drone, edict_t *ent, int drone_type, return drone; } -edict_t *vrx_create_new_drone(edict_t *ent, int drone_type, qboolean worldspawn, qboolean link_now) +edict_t *vrx_create_new_drone(edict_t *ent, int drone_type, qboolean worldspawn, qboolean link_now, int bonus_level) { - return vrx_create_drone_from_ent(G_Spawn(), ent, drone_type, worldspawn, link_now); + return vrx_create_drone_from_ent(G_Spawn(), ent, drone_type, worldspawn, link_now, bonus_level); } void RemoveAllDrones (edict_t *ent, qboolean refund_player) @@ -2695,35 +2690,35 @@ void Cmd_Drone_f (edict_t *ent) } if (!Q_strcasecmp(s, "gunner")) - vrx_create_new_drone(ent, 1, false, true); + vrx_create_new_drone(ent, 1, false, true, 0); else if (!Q_strcasecmp(s, "parasite")) - vrx_create_new_drone(ent, 2, false, true); + vrx_create_new_drone(ent, 2, false, true, 0); else if (!Q_strcasecmp(s, "brain")) - vrx_create_new_drone(ent, 4, false, true); + vrx_create_new_drone(ent, 4, false, true, 0); else if (!Q_strcasecmp(s, "praetor")) - vrx_create_new_drone(ent, 3, false, true); + vrx_create_new_drone(ent, 3, false, true, 0); else if (!Q_strcasecmp(s, "medic")) - vrx_create_new_drone(ent, 5, false, true); + vrx_create_new_drone(ent, 5, false, true, 0); else if (!Q_strcasecmp(s, "tank")) - vrx_create_new_drone(ent, 6, false, true); + vrx_create_new_drone(ent, 6, false, true, 0); else if (!Q_strcasecmp(s, "mutant")) - vrx_create_new_drone(ent, 7, false, true); + vrx_create_new_drone(ent, 7, false, true, 0); else if (!Q_strcasecmp(s, "gladiator")/* && ent->myskills.administrator*/) - vrx_create_new_drone(ent, 8, false, true); + vrx_create_new_drone(ent, 8, false, true, 0); else if (!Q_strcasecmp(s, "berserker")) - vrx_create_new_drone(ent, 9, false, true); + vrx_create_new_drone(ent, 9, false, true, 0); else if (!Q_strcasecmp(s, "soldier")) - vrx_create_new_drone(ent, 10, false, true); + vrx_create_new_drone(ent, 10, false, true, 0); else if (!Q_strcasecmp(s, "enforcer")) - vrx_create_new_drone(ent, 11, false, true); + vrx_create_new_drone(ent, 11, false, true, 0); else if (!Q_strcasecmp(s, "flyer")) - vrx_create_new_drone(ent, 12, false, true); + vrx_create_new_drone(ent, 12, false, true, 0); else if (!Q_strcasecmp(s, "floater")) - vrx_create_new_drone(ent, 13, false, true); + vrx_create_new_drone(ent, 13, false, true, 0); else if (!Q_strcasecmp(s, "hover")) - vrx_create_new_drone(ent, 14, false, true); + vrx_create_new_drone(ent, 14, false, true, 0); else if (!Q_strcasecmp(s, "shambler")) - vrx_create_new_drone(ent, 15, false, true); + vrx_create_new_drone(ent, 15, false, true, 0); //else if (!Q_strcasecmp(s, "baron fire") && ent->myskills.administrator) //vrx_create_new_drone(ent, 32, false, true); //else if (!Q_strcasecmp(s, "jorg")) diff --git a/src/entities/g_spawn.c b/src/entities/g_spawn.c index 4d9ed19..e61ad09 100644 --- a/src/entities/g_spawn.c +++ b/src/entities/g_spawn.c @@ -1081,79 +1081,78 @@ char *dm_statusbar = //GHz END ; -edict_t * -vrx_create_drone_from_ent(edict_t *drone, edict_t *ent, int drone_type, qboolean worldspawn, qboolean link_now); + void SP_monster_berserk(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 9, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 9, true, true, 0); } void SP_monster_gladiator(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 8, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 8, true, true, 0); } void SP_monster_gunner(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 1, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 1, true, true, 0); } void SP_monster_soldier(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 10, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 10, true, true, 0); } void SP_monster_tank(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 6, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 6, true, true, 0); } void SP_monster_tank_commander(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 30, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 30, true, true, 0); } void SP_monster_infantry(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 11, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 11, true, true, 0); } void SP_monster_medic(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 5, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 5, true, true, 0); } void SP_monster_mutant(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 7, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 7, true, true, 0); } void SP_monster_chick(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 3, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 3, true, true, 0); } void SP_monster_parasite(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 2, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 2, true, true, 0); } void SP_monster_brain(edict_t *ent) { if (coop->value) - vrx_create_drone_from_ent(ent, g_edicts, 4, true, true); + vrx_create_drone_from_ent(ent, g_edicts, 4, true, true, 0); } diff --git a/src/g_local.h b/src/g_local.h index f7843fb..a53106f 100644 --- a/src/g_local.h +++ b/src/g_local.h @@ -466,6 +466,10 @@ typedef struct qboolean has_red_fallback; } ctf; + struct { + int level_bonus; + float time_to_next_respawn; + } pvm; /* gdsfiles_t gdsfiles[MAX_CLIENTS];*/ @@ -894,6 +898,7 @@ extern cvar_t *flood_msgs; extern cvar_t *flood_persecond; extern cvar_t *flood_waitdelay; extern cvar_t *gamedir; +extern cvar_t *hostname; extern cvar_t *dm_monsters; extern cvar_t *reconnect_ip; extern cvar_t *invasion_enabled; @@ -1264,7 +1269,9 @@ void M_CheckGround (edict_t *ent); void M_SetEffects (edict_t *ent); void M_MoveFrame (edict_t *self); void M_WorldEffects (edict_t *ent); -edict_t *vrx_create_new_drone(edict_t *ent, int drone_type, qboolean worldspawn, qboolean link_now); +edict_t *vrx_create_new_drone(edict_t *ent, int drone_type, qboolean worldspawn, qboolean link_now, int bonus_level); +edict_t * +vrx_create_drone_from_ent(edict_t *drone, edict_t *ent, int drone_type, qboolean worldspawn, qboolean link_now, int bonus_level); // // g_misc.c diff --git a/src/gamemodes/invasion.c b/src/gamemodes/invasion.c index 87d3d37..87eae30 100644 --- a/src/gamemodes/invasion.c +++ b/src/gamemodes/invasion.c @@ -12,6 +12,7 @@ int invasion_spawncount; // current spawns int invasion_monsterspawns; int invasion_navicount; int invasion_start_navicount; +int invasion_bonus_levels = 0; edict_t *INV_PlayerSpawns[64]; edict_t *INV_Navi[64]; edict_t *INV_StartNavi[64]; @@ -68,6 +69,7 @@ void INV_Init(void) invasion_spawncount = 0; invasion_navicount = 0; invasion_start_navicount = 0; + invasion_bonus_levels = 0; for (i = 0; i < 64; i++) { INV_PlayerSpawns[i] = NULL; @@ -432,12 +434,11 @@ void INV_AwardPlayers(void) edict_t* INV_SpawnDrone(edict_t* self, edict_t *spawn_point, int index) { - edict_t *monster; + edict_t *monster = vrx_create_new_drone(self, index, true, false, invasion_bonus_levels); vec3_t start; - trace_t tr; int mhealth = 1; - if (!(monster = vrx_create_new_drone(self, index, true, false))) + if (!monster) { //gi.dprintf("INV_SpawnDrone() failed to create a new type %d drone\n", index); return NULL; @@ -447,7 +448,7 @@ edict_t* INV_SpawnDrone(edict_t* self, edict_t *spawn_point, int index) VectorCopy(spawn_point->s.origin, start); start[2] = spawn_point->absmax[2] + 1 + fabsf(monster->mins[2]); - tr = gi.trace(start, monster->mins, monster->maxs, start, NULL, MASK_SHOT); + trace_t tr = gi.trace(start, monster->mins, monster->maxs, start, NULL, MASK_SHOT); // starting point is occupied if (tr.fraction < 1) @@ -620,6 +621,20 @@ void INV_BossCheck(edict_t *self) invasion_data.boss = NULL; } +void INV_Change_Level(int amt) +{ + invasion_difficulty_level += amt; + + if (invasion_difficulty_level > 1) + // fixed difficulty pacing + invasion_bonus_levels = (int)sqrt(invasion_difficulty_level - 1); + else + { + // cumulative difficulty + invasion_bonus_levels += (int)sqrt(invasion_difficulty_level); + } +} + void INV_OnTimeout(edict_t *self) { qboolean was_boss = false; gi.bprintf(PRINT_HIGH, "Time's up!\n"); @@ -645,10 +660,10 @@ void INV_OnTimeout(edict_t *self) { } // increase the difficulty level for the next wave - //if (invasion->value == 1) - // invasion_difficulty_level += 1; - //else - // invasion_difficulty_level += 2; // Hard mode. + if (invasion->value == 1) + INV_Change_Level(1); + else + INV_Change_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); @@ -861,7 +876,8 @@ qboolean INV_Spawnstate_Working(edict_t *self, const int players, int max_monste if (invasion_data.mspawned >= max_monsters) { // increase the difficulty level for the next wave - invasion_difficulty_level += 1; + INV_Change_Level(1); + invasion_data.printedmessage = 0; invasion_data.mspawned = 0; self->count = MONSTERSPAWN_STATUS_IDLE; @@ -1190,7 +1206,7 @@ void inv_defenderspawn_think(edict_t *self) // try to spawn another if ((level.time > self->wait) - && (monster = vrx_create_new_drone(self, self->sounds, true, false)) != NULL) + && (monster = vrx_create_new_drone(self, self->sounds, true, false, 0)) != NULL) { //gi.dprintf("%d: attempting to spawn a monster\n", num); // get starting position diff --git a/src/quake2/g_layout.c b/src/quake2/g_layout.c index 6555334..0096a8e 100644 --- a/src/quake2/g_layout.c +++ b/src/quake2/g_layout.c @@ -506,6 +506,14 @@ void layout_generate_misc(edict_t* ent, sidebar_t* sidebar) sidebar_add_entry(sidebar, entry); } + if (pvm->value && pregame_time->value < level.time && !invasion->value) { + sidebar_entry_t entry = { 0 }; + entry.pos = sidebar_get_next_line_pos(sidebar); + entry.name = lva("pvm"); + entry.data = lva("%.0fs/%d", level.pvm.time_to_next_respawn, level.pvm.level_bonus); + sidebar_add_entry(sidebar, entry); + } + if (ent->client->tele_timeout > level.framenum) { sidebar_entry_t entry = { 0 }; diff --git a/src/quake2/g_main.c b/src/quake2/g_main.c index 6aded87..ba26cac 100644 --- a/src/quake2/g_main.c +++ b/src/quake2/g_main.c @@ -99,6 +99,7 @@ int invasion_difficulty_level; qboolean found_flag; cvar_t *gamedir; +cvar_t *hostname; cvar_t *dm_monsters; cvar_t *pvm_respawntime; cvar_t *pvm_monstermult; diff --git a/src/quake2/g_save.c b/src/quake2/g_save.c index 903357c..82d0bdc 100644 --- a/src/quake2/g_save.c +++ b/src/quake2/g_save.c @@ -281,6 +281,7 @@ void InitGame(void) vrx_password = gi.cvar("vrx_password", "", CVAR_ARCHIVE | CVAR_USERINFO); dm_monsters = gi.cvar("dm_monsters", "8", CVAR_SERVERINFO); + hostname = gi.cvar("hostname", "q2vortex.com", CVAR_SERVERINFO); // vrxchile v1.3 ally half server allies = gi.cvar("allies", "1", CVAR_SERVERINFO | CVAR_LATCH); @@ -312,9 +313,9 @@ void InitGame(void) // az end // az: pvm_respawntime, pvm_monstermult and ffa_monstermult currently unused - pvm_respawntime = gi.cvar("pvm_respawntime", "10", 0); + pvm_respawntime = gi.cvar("pvm_respawntime", "15", 0); pvm_monstermult = gi.cvar("pvm_monstermult", "1.0", 0); - ffa_respawntime = gi.cvar("ffa_respawntime", "20", 0); + ffa_respawntime = gi.cvar("ffa_respawntime", "15", 0); ffa_monstermult = gi.cvar("ffa_monstermult", "1.0", 0); // az note: only used in teamplay.c, which is unused.... diff --git a/src/quake2/g_svcmds.c b/src/quake2/g_svcmds.c index 9c45261..0a057ae 100644 --- a/src/quake2/g_svcmds.c +++ b/src/quake2/g_svcmds.c @@ -609,35 +609,35 @@ void SVCmd_SpawnBoss_f (void) if (invasion->value) INV_SpawnBoss(m_worldspawn, 30); else - vrx_create_new_drone(m_worldspawn, 30, true, true); + vrx_create_new_drone(m_worldspawn, 30, true, true, 0); } else if (!strcmp(gi.argv(2), "makron")) { if (invasion->value) INV_SpawnBoss(m_worldspawn, 31); else - vrx_create_new_drone(m_worldspawn, 31, true, true); + vrx_create_new_drone(m_worldspawn, 31, true, true, 0); } else if (!strcmp(gi.argv(2), "firebaron")) { if (invasion->value) INV_SpawnBoss(m_worldspawn, 32); else - vrx_create_new_drone(m_worldspawn, 32, true, true); + vrx_create_new_drone(m_worldspawn, 32, true, true, 0); } else if (!strcmp(gi.argv(2), "supertank")) { if (invasion->value) INV_SpawnBoss(m_worldspawn, 33); else - vrx_create_new_drone(m_worldspawn, 33, true, true); + vrx_create_new_drone(m_worldspawn, 33, true, true, 0); } else if (!strcmp(gi.argv(2), "jorg")) { if (invasion->value) INV_SpawnBoss(m_worldspawn, 34); else - vrx_create_new_drone(m_worldspawn, 34, true, true); + vrx_create_new_drone(m_worldspawn, 34, true, true, 0); } else safe_cprintf(NULL, PRINT_HIGH, "Invalid boss type. Usage: sv spawnboss \n");