diff --git a/src/gs-entbase/server.src b/src/gs-entbase/server.src index 32df931c..3928324d 100644 --- a/src/gs-entbase/server.src +++ b/src/gs-entbase/server.src @@ -91,6 +91,7 @@ server/multi_manager.cpp server/momentarybase.cpp server/momentary_rot_button.cpp server/momentary_door.cpp +server/func_mortar_field.cpp server/monster_furniture.cpp server/monster_generic.cpp server/monstermaker.cpp diff --git a/src/gs-entbase/server/func_mortar_field.cpp b/src/gs-entbase/server/func_mortar_field.cpp new file mode 100644 index 00000000..37c15fbc --- /dev/null +++ b/src/gs-entbase/server/func_mortar_field.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/*QUAKED func_mortar_field (0 .5 .8) ? +"targetname" Name +"m_flSpread" Maximum spread in game-units +"m_flCount" Number of bombs dropped per strike +"m_flControl" Targeting type. 0 = random, 1 = activator, 2 = controlled +"m_iszXController" Name of the momentary_rot_button providing X-offset +"m_iszYController" Name of the momentary_rot_button providing Y-offset + +Description: +This brush volume acts as mortar drop area. +When triggered, it'll drop mortar shells straight to the ground (with a bit +of spread if specified). + +It can be set to three different targeting modes, 0 will pick any +random point in the volume as a drop position. 1 will target the person or +entity activating it and 2 is a more complex mode which requires two +momentary_rot_button entities to control the X and Y offset in the volume. + +Notes: +GoldSrc expects some hardcoded behaviour (sounds playing, hardcoded delay +between mortar shell drops) that I haven't implemented yet. +I'll turn those into map attribute keys so people can finally control +sound, damage, delay and so on. + +Trivia: +This entity was introduced in Half-Life (1998). +*/ + +class func_mortar_field:CBaseTrigger +{ + int m_iType; + int m_iCount; + float m_flSpread; + string m_strXController; + string m_strYController; + + void(void) func_mortar_field; + + virtual void(vector) Fire; + virtual void(void) FireRandom; + virtual void(entity) FireTarget; + virtual void(void) FireControlled; + virtual void(entity,int) Trigger; + virtual void(void) Respawn; +}; + +void +func_mortar_field::Fire(vector vecOrg) +{ + /* the spread */ + makevectors([90,0,0]); + vecOrg[0] += random(-m_flSpread, m_flSpread); + vecOrg[1] += random(-m_flSpread, m_flSpread); + + /* trace from the sky downwards */ + traceline(vecOrg, vecOrg + (v_forward * 4096), FALSE, this); + + float dmg = 200.0f; + Damage_Radius(trace_endpos, this, dmg, dmg * 2.5f, TRUE, 0); + FX_Explosion(trace_endpos); +} + +void +func_mortar_field::FireRandom(void) +{ + vector vecPos; + + /* get our center */ + vecPos[0] = absmin[0] + (0.5f * (absmax[0] - absmin[0])); + vecPos[1] = absmin[1] + (0.5f * (absmax[1] - absmin[1])); + vecPos[2] = absmin[2] + (0.5f * (absmax[2] - absmin[2])); + + /* now randomize the position in the volume */ + vecPos[0] += mins[0] + (random() * size[0]); + vecPos[1] += mins[1] + (random() * size[1]); + + for (int i = 0; i < m_iCount; i++); + Fire(vecPos); +} + +void +func_mortar_field::FireTarget(entity act) +{ + vector vecPos; + + /* get our center */ + vecPos[0] = absmin[0] + (0.5f * (absmax[0] - absmin[0])); + vecPos[1] = absmin[1] + (0.5f * (absmax[1] - absmin[1])); + vecPos[2] = absmin[2] + (0.5f * (absmax[2] - absmin[2])); + + /* orient towards the nearest player pos, clamping by our bounds */ + vecPos[0] = bound(vecPos[0] + mins[0], act.origin[0], vecPos[0] + maxs[0]); + vecPos[1] = bound(vecPos[1] + mins[1], act.origin[1], vecPos[1] + maxs[0]); + + for (int i = 0; i < m_iCount; i++); + Fire(vecPos); +} + +void +func_mortar_field::FireControlled(void) +{ + momentary_rot_button mX; + momentary_rot_button mY; + vector vecPos; + entity f; + + mX = mY = __NULL__; + + for (f = world; (f = find(f, ::classname, "momentary_rot_button"));) { + momentary_rot_button l = (momentary_rot_button) f; + + if (l.m_strTargetName == m_strXController) { + mX = l; + } + + if (l.m_strTargetName == m_strYController) { + mY = l; + } + } + + if (!mX || !mY) + return; + + /* find our center */ + vecPos[0] = absmin[0] + (0.5f * (absmax[0] - absmin[0])); + vecPos[1] = absmin[1] + (0.5f * (absmax[1] - absmin[1])); + vecPos[2] = absmin[2] + (0.5f * (absmax[2] - absmin[2])); + + /* now offset the position to the rot_buttons */ + vecPos[0] += mins[0] + (mX.m_flProgress * size[0]); + vecPos[1] += mins[1] + (mY.m_flProgress * size[1]); + + for (int i = 0; i < m_iCount; i++); + Fire(vecPos); +} + +void +func_mortar_field::Trigger(entity act, int state) +{ + switch (m_iType) { + case 0: + FireRandom(); + break; + case 1: + FireTarget(act); + break; + case 2: + FireControlled(); + break; + default: + break; + } +} + +void +func_mortar_field::Respawn(void) +{ + SetMovetype(MOVETYPE_NONE); + SetSolid(SOLID_NOT); + SetRenderMode(RM_TRIGGER); + SetModel(m_oldModel); + SetOrigin(m_oldOrigin); +} + +void +func_mortar_field::func_mortar_field(void) +{ + for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) { + switch (argv(i)) { + case "m_iszXController": + m_strXController = argv(i+1); + break; + case "m_iszYController": + m_strYController = argv(i+1); + break; + case "m_flControl": + m_iType = stoi(argv(i+1)); + break; + case "m_flCount": + m_iCount = stoi(argv(i+1)); + break; + case "m_flSpread": + m_flSpread = stof(argv(i+1)) / 2; + break; + default: + break; + } + } + + CBaseTrigger::CBaseTrigger(); +} diff --git a/src/gs-entbase/server/momentarybase.cpp b/src/gs-entbase/server/momentarybase.cpp index bf5f298e..bcc18af2 100644 --- a/src/gs-entbase/server/momentarybase.cpp +++ b/src/gs-entbase/server/momentarybase.cpp @@ -14,13 +14,6 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/*QUAKED func_wall (0 .5 .8) ? -"targetname" Name - -Brush that lets light to pass through it. -On idTech 2 BSPs, it will change texture variants when triggered. -*/ - class CBaseMomentary:CBaseTrigger { entity m_eUser;