diff --git a/src/gs-entbase/server/monstermaker.cpp b/src/gs-entbase/server/monstermaker.cpp index 186ff0cd..47a8f68a 100644 --- a/src/gs-entbase/server/monstermaker.cpp +++ b/src/gs-entbase/server/monstermaker.cpp @@ -14,50 +14,195 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/*QUAKED monstermaker (1 0 0) (-8 -8 -8) (8 8 8) +/*QUAKED monstermaker (1 0 0) (-8 -8 -8) (8 8 8) MMF_STARTON x MMF_NONTOGGLE MMF_MONSTERCLIP "targetname" Name "target" Target when triggered. "killtarget" Target to kill when triggered. -All it does right now is spawn snarks, regardless of what monster you want to -spawn. +"monstertype" Type of monster to spawn, represents their entity classname. +"monstercount" Maximum amount of monsters you want spawned in total. +"delay" Delay between spawns in seconds. +"child_name" Applies this as a 'targetname' to spawned monsters. +"child_alivemax" Maximum amount of spawned monsters that are alive at a time. + +The monster maker is the end-all solution to timed/controlled spawning of +monster entities. + +When MMF_STARTON is checked, it'll start on automatically. +When MMF_NONTOGGLE is checked, it'll spawn only one monster with each trigger +When MMF_MONSTERCLIP is checked, all spawned monsters will be blocked by +func_monsterclip entities. */ -class monstermaker : CBaseTrigger -{ - string m_strMonster; - - void() monstermaker; - virtual void() Trigger; +enumflags { + MMF_STARTON, + MMF_UNUSED1, + MMF_NONTOGGLE, + MMF_MONSTERCLIP }; -void monstermaker::Trigger ( void ) +class monstermaker:CBaseTrigger +{ + string m_strMonster; + int m_iMonsterSpawned; + int m_iMonsterCount; + float m_flDelay; + int m_iMaxChildren; + int m_iEnabled; + string m_strChildName; + + void() monstermaker; + + virtual void() Spawner; + virtual void() Trigger; + virtual void() Respawn; + virtual void() TurnOn; + virtual void() TurnOff; + virtual int() GetValue; +}; + +int +monstermaker::GetValue(void) +{ + return m_iEnabled; +} + +void +monstermaker::TurnOff(void) +{ + think = __NULL__; + nextthink = 0; + m_iEnabled = 0; +} + +void +monstermaker::TurnOn(void) +{ + think = Spawner; + nextthink = time + m_flDelay; + m_iEnabled = 1; +} + +void +monstermaker::Spawner(void) { static void monstermaker_spawnunit(void) { + /* these will get overwritten by the monster spawnfunction */ + vector neworg = self.origin; + string tname = self.netname; + + /* become the classname assigned */ + CBaseMonster t = (CBaseMonster)self; callfunction(self.classname); + + /* apply the saved values back */ + t.origin = t.m_oldOrigin = neworg; + t.m_strTargetName = tname; + + /* spawn anew */ + t.Respawn(); + } + + int c = 0; + + /* look and count the buggers that are still around */ + for (entity l = world; (l = find(l, ::classname, m_strMonster));) { + if (l.real_owner == this) { + /* may be a corpse? */ + if (l.health > 0 && l.movetype == MOVETYPE_WALK) { + c++; + } + } + } + + /* too many alive at a time */ + if ((c >= m_iMaxChildren) || (m_flDelay == 0 && c >= 1)) { + nextthink = time + m_flDelay; + return; } if (isfunction(strcat("spawnfunc_", m_strMonster))) { entity unit = spawn(); unit.classname = strcat("spawnfunc_", m_strMonster); + unit.netname = m_strChildName; unit.think = monstermaker_spawnunit; unit.nextthink = time + 0.1f; + unit.real_owner = this; dprint(sprintf("^2monstermaker::^3Trigger^7: Spawning %s\n", m_strMonster)); setorigin(unit, origin); + m_iMonsterSpawned++; + + if (m_strTarget) { + UseTargets(); + } + + /* inherit the monsterclip flag */ + if (spawnflags & MMF_MONSTERCLIP) { + unit.spawnflags |= MSF_MONSTERCLIP; + } } else { print(sprintf("^1monstermaker::^3Trigger^7: cannot call spawnfunction for %s\n", m_strMonster)); } + + /* shut off for good when we've spawned all we ever wanted */ + if (m_iMonsterSpawned >= m_iMonsterCount) { + think = __NULL__; + return; + } + + /* sometimes all we do is just spawn a single monster at a time */ + if (spawnflags & MMF_NONTOGGLE) { + TurnOff(); + } else { + nextthink = time + m_flDelay; + } } -void monstermaker :: monstermaker ( void ) +void +monstermaker::Trigger(void) +{ + if (m_iEnabled) + TurnOff(); + else + TurnOn(); +} + +void +monstermaker::Respawn(void) +{ + if (spawnflags & MMF_STARTON) { + TurnOn(); + } else { + TurnOff(); + } + + m_iMonsterSpawned = 0; +} + +void +monstermaker::monstermaker(void) { CBaseTrigger::CBaseTrigger(); - for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) { - switch ( argv( i ) ) { + for (int i = 1; i < ( tokenize(__fullspawndata) - 1); i += 2) { + switch (argv(i)) { case "monstertype": m_strMonster = argv(i+1); break; + case "monstercount": + m_iMonsterCount = stoi(argv(i+1)); + break; + case "child_alivemax": + case "m_imaxlivechildren": + m_iMaxChildren = stoi(argv(i+1)); + break; + case "delay": + m_flDelay = stof(argv(i+1)); + break; + case "child_name": + case "netname": + m_strChildName = argv(i+1); + netname = __NULL__; default: break; } diff --git a/src/server/cstrike/player.c b/src/server/cstrike/player.c index 0a0687e8..c5a0398e 100644 --- a/src/server/cstrike/player.c +++ b/src/server/cstrike/player.c @@ -203,3 +203,14 @@ void CSEv_PlayerSwitchWeapon_f(float w) pl.activeweapon = (int)w; Weapons_Draw(); } + +void +Player_Precache(void) +{ + searchhandle pm; + pm = search_begin("models/player/*/*.mdl", TRUE, TRUE); + for (int i = 0; i < search_getsize(pm); i++) { + precache_model(search_getfilename(pm, i)); + } + search_end(pm); +} diff --git a/src/server/scihunt/server.c b/src/server/scihunt/server.c index 8e743289..291a9a41 100644 --- a/src/server/scihunt/server.c +++ b/src/server/scihunt/server.c @@ -30,16 +30,7 @@ void Game_Worldspawn(void) precache_model("models/w_weaponbox.mdl"); precache_sound("fvox/flatline.wav"); - /* TODO: Scan and precache models/player/.mdl */ - precache_model("models/player/barney/barney.mdl"); - precache_model("models/player/gman/gman.mdl"); - precache_model("models/player/gordon/gordon.mdl"); - precache_model("models/player/hgrunt/hgrunt.mdl"); - precache_model("models/player/scientist/scientist.mdl"); - precache_model("models/player/zombie/zombie.mdl"); - precache_model("models/player/helmet/helmet.mdl"); - precache_model("models/player/recon/recon.mdl"); - precache_model("models/player/robo/robo.mdl"); + Player_Precache(); Weapons_Init(); SHData_Parse(mapname); } diff --git a/src/server/valve/player.c b/src/server/valve/player.c index 859d8e5a..d05649c2 100644 --- a/src/server/valve/player.c +++ b/src/server/valve/player.c @@ -204,3 +204,14 @@ void CSEv_PlayerSwitchWeapon_f(float w) pl.activeweapon = (int)w; Weapons_Draw(); } + +void +Player_Precache(void) +{ + searchhandle pm; + pm = search_begin("models/player/*/*.mdl", TRUE, TRUE); + for (int i = 0; i < search_getsize(pm); i++) { + precache_model(search_getfilename(pm, i)); + } + search_end(pm); +} diff --git a/src/server/valve/server.c b/src/server/valve/server.c index 2629d319..8470e51b 100644 --- a/src/server/valve/server.c +++ b/src/server/valve/server.c @@ -30,15 +30,7 @@ void Game_Worldspawn(void) precache_model("models/w_weaponbox.mdl"); precache_sound("fvox/flatline.wav"); - /* TODO: Scan and precache models/player/.mdl */ - precache_model("models/player/barney/barney.mdl"); - precache_model("models/player/gman/gman.mdl"); - precache_model("models/player/gordon/gordon.mdl"); - precache_model("models/player/hgrunt/hgrunt.mdl"); - precache_model("models/player/scientist/scientist.mdl"); - precache_model("models/player/zombie/zombie.mdl"); - precache_model("models/player/helmet/helmet.mdl"); - precache_model("models/player/recon/recon.mdl"); - precache_model("models/player/robo/robo.mdl"); + Player_Precache(); Weapons_Init(); + Player_Precache(); } diff --git a/src/shared/gearbox/w_displacer.c b/src/shared/gearbox/w_displacer.c index 128ea0c2..e4aedaf1 100644 --- a/src/shared/gearbox/w_displacer.c +++ b/src/shared/gearbox/w_displacer.c @@ -286,7 +286,7 @@ w_displacer_hud(void) vector cross_pos; vector aicon_pos; - cross_pos = (g_hudres / 2) + [-12,-12]; + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; drawsubpic( diff --git a/src/shared/gearbox/w_eagle.c b/src/shared/gearbox/w_eagle.c index d6631ff4..6b7e1ee3 100644 --- a/src/shared/gearbox/w_eagle.c +++ b/src/shared/gearbox/w_eagle.c @@ -274,7 +274,7 @@ w_eagle_crosshair(void) lerp = Math_Lerp(18,6, trace_fraction); jitter[0] = (random(0,2) - 2) * (1 - trace_fraction); jitter[1] = (random(0,2) - 2) * (1 - trace_fraction); - cross_pos = (g_hudres / 2) + ([-lerp,-lerp] / 2); + cross_pos = g_hudmins + (g_hudres / 2) + ([-lerp,-lerp] / 2); drawsubpic( cross_pos + jitter, [lerp,lerp], @@ -286,7 +286,7 @@ w_eagle_crosshair(void) DRAWFLAG_ADDITIVE ); } else { - cross_pos = (g_hudres / 2) + [-12,-12]; + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; drawsubpic( cross_pos, [24,24], diff --git a/src/shared/gearbox/w_m249.c b/src/shared/gearbox/w_m249.c index 49ca9cb9..a45c3365 100644 --- a/src/shared/gearbox/w_m249.c +++ b/src/shared/gearbox/w_m249.c @@ -224,7 +224,7 @@ w_m249_crosshair(void) vector aicon_pos; /* crosshair */ - cross_pos = (g_hudres / 2) + [-12,-12]; + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; drawsubpic( cross_pos, [24,24], diff --git a/src/shared/gearbox/w_shockrifle.c b/src/shared/gearbox/w_shockrifle.c index 5a2f4616..7d746c81 100644 --- a/src/shared/gearbox/w_shockrifle.c +++ b/src/shared/gearbox/w_shockrifle.c @@ -218,7 +218,7 @@ w_shockrifle_crosshair(void) vector aicon_pos; /* crosshair */ - cross_pos = (g_hudres / 2) + [-12,-12]; + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; drawsubpic( cross_pos, [24,24], diff --git a/src/shared/gearbox/w_sporelauncher.c b/src/shared/gearbox/w_sporelauncher.c index aedb6522..7e407eee 100644 --- a/src/shared/gearbox/w_sporelauncher.c +++ b/src/shared/gearbox/w_sporelauncher.c @@ -276,7 +276,7 @@ w_sporelauncher_crosshair(void) vector aicon_pos; /* crosshair */ - cross_pos = (g_hudres / 2) + [-12,-12]; + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; drawsubpic( cross_pos, [24,24], diff --git a/src/shared/valve/w_snark.c b/src/shared/valve/w_snark.c index 4979866f..96ce1960 100644 --- a/src/shared/valve/w_snark.c +++ b/src/shared/valve/w_snark.c @@ -108,7 +108,6 @@ void monster_snark::Respawn(void) { netname = "Snark"; - classname = "snark"; setmodel(this, "models/w_squeak.mdl"); flags |= FL_MONSTER; solid = SOLID_BBOX;