/* =========================================================================== Copyright (C) 2024 the OpenMoHAA team This file is part of OpenMoHAA source code. OpenMoHAA source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. OpenMoHAA source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "smokegrenade.h" #include "smokesprite.h" #include "level.h" #include "sentient.h" Event EV_SmokeGrenade_SetSpawnRate ( "spawnrate", EV_DEFAULT, "f", "rate", "sets how many smoke volumes are spawned per second" ); Event EV_SmokeGrenade_SetBouncefactor ( "bouncefactor", EV_DEFAULT, "f", "factor", "sets how far smoke volumes bounce when they collide with something" ); Event EV_SmokeGrenade_SetLife ( "life", EV_DEFAULT, "f", "life", "sets how long the smoke emitter lives" ); Event EV_SmokeGrenade_SetSpawnLife ( "spawnlife", EV_DEFAULT, "f", "life", "sets how long each smoke volume lives" ); Event EV_SmokeGrenade_SetScalerate ( "scalerate", EV_DEFAULT, "f", "rate", "sets how fast the smoke volume grows" ); Event EV_SmokeGrenade_SetVelocity ( "velocity", EV_DEFAULT, "fff", "vel_x vel_y vel_z", "sets how fast the smoke volume moves away, with x forward and z up" ); Event EV_SmokeGrenade_SetSpin ( "spin", EV_DEFAULT, "f", "avel", "sets the number of rotations per second for this entity around its z axis" ); Event EV_SmokeGrenade_SetOffset ( "offset", EV_DEFAULT, "fff", "offset_x offset_y offset_z", "sets offset of the smoke volume from the entity" ); Event EV_SmokeGrenade_SetScale ( "scale", EV_DEFAULT, "f", "scale", "sets initial scale of each smoke volume" ); Event EV_SmokeGrenade_SetFadein ( "fadein", EV_DEFAULT, "f", "time", "sets fadein time from 0 alpha to 1 alpha, in seconds" ); Event EV_SmokeGrenade_SetFadedelay ( "fadedelay", EV_DEFAULT, "f", "time", "sets how long the entity waits until fading out from 1 alpha to 0 alpha, in seconds" ); Event EV_SmokeGrenade_SetMaxAlpha ( "maxalpha", EV_DEFAULT, "f", "alpha", "sets maximum opacity of an individual smoke particle, in 0-1 range" ); CLASS_DECLARATION(EffectEntity, SmokeGrenade, "smokegrenade") { {&EV_SmokeGrenade_SetSpawnRate, &SmokeGrenade::EventSetSpawnrate }, {&EV_SmokeGrenade_SetBouncefactor, &SmokeGrenade::EventSetBouncefactor}, {&EV_SmokeGrenade_SetLife, &SmokeGrenade::EventSetLife }, {&EV_SmokeGrenade_SetSpawnLife, &SmokeGrenade::EventSetSpawnLife }, {&EV_SmokeGrenade_SetScalerate, &SmokeGrenade::EventSetScalerate }, {&EV_SmokeGrenade_SetVelocity, &SmokeGrenade::EventSetVelocity }, {&EV_SmokeGrenade_SetSpin, &SmokeGrenade::EventSetSpin }, {&EV_SmokeGrenade_SetOffset, &SmokeGrenade::EventSetOffset }, {&EV_SmokeGrenade_SetScale, &SmokeGrenade::EventSetScale }, {&EV_SmokeGrenade_SetFadein, &SmokeGrenade::EventSetFadein }, {&EV_SmokeGrenade_SetFadedelay, &SmokeGrenade::EventSetFadedelay }, {&EV_SmokeGrenade_SetMaxAlpha, &SmokeGrenade::EventSetMaxAlpha }, {NULL, NULL } }; void SmokeGrenade::EventSetSpawnrate(Event *ev) { float rate = ev->GetFloat(1); if (rate < 0.001f) { rate = 0.001f; } spawnRate = 1000.0f / rate; } void SmokeGrenade::EventSetBouncefactor(Event *ev) { bounceFactor = ev->GetFloat(1); } void SmokeGrenade::EventSetLife(Event *ev) { nextRemoveTime = level.time + ev->GetFloat(1); } void SmokeGrenade::EventSetSpawnLife(Event *ev) { spawnLife = ev->GetFloat(1); } void SmokeGrenade::EventSetScalerate(Event *ev) { scaleRate = ev->GetFloat(1); } void SmokeGrenade::EventSetVelocity(Event *ev) { velocity[0] = ev->GetFloat(1); velocity[1] = ev->GetFloat(2); velocity[2] = ev->GetFloat(3); } void SmokeGrenade::EventSetSpin(Event *ev) { spinRate = ev->GetFloat(1); } void SmokeGrenade::EventSetOffset(Event *ev) { offset[0] = ev->GetFloat(1); offset[1] = ev->GetFloat(2); offset[2] = ev->GetFloat(3); } void SmokeGrenade::EventSetScale(Event *ev) { scale = ev->GetFloat(1) * 0.5; } void SmokeGrenade::EventSetFadein(Event *ev) { fadeIn = ev->GetFloat(1); } void SmokeGrenade::EventSetFadedelay(Event *ev) { fadeDelay = ev->GetFloat(1); } void SmokeGrenade::EventSetMaxAlpha(Event *ev) { maxAlpha = ev->GetFloat(1); } SmokeGrenade::SmokeGrenade() { flags |= FL_THINK; nextRemoveTime = level.time + 1.0; spawnRate = 1000; bounceFactor = 0.0; spawnLife = 1.0; scaleRate = 1.0; velocity = vec_zero; offset = vec_zero; spinRate = 0.0; scale = 1.0; fadeIn = 0.0; fadeDelay = spawnLife; maxAlpha = 1.0; lastSpawnTime = level.inttime + 150; } void SmokeGrenade::Think() { if (level.time >= nextRemoveTime) { Delete(); return; } if (level.inttime >= lastSpawnTime + spawnRate) { SmokeSprite sp; float degrees; lastSpawnTime += spawnRate; sp.origin = origin; sp.spawnTime = level.time; sp.scale = scale; degrees = angles.y + (((level.inttime / 1000.0 - 176.0) * spinRate) * -0.36); RotatePointAroundAxis(sp.velocity, 2, velocity, degrees); sp.spawnLife = spawnLife; sp.bounceFactor = bounceFactor; sp.scaleStart = scale; sp.scaleRate = scaleRate; sp.fadeIn = fadeIn; sp.fadeDelay = fadeDelay; sp.maxAlpha = maxAlpha; sp.owner = owner; G_AddSmokeSprite(&sp); } } void SmokeGrenade::Archive(Archiver& arc) { EffectEntity::Archive(arc); arc.ArchiveFloat(&nextRemoveTime); arc.ArchiveInteger(&spawnRate); arc.ArchiveFloat(&bounceFactor); arc.ArchiveFloat(&spawnLife); arc.ArchiveFloat(&scaleRate); arc.ArchiveVector(&velocity); arc.ArchiveFloat(&spinRate); arc.ArchiveVector(&offset); arc.ArchiveFloat(&scale); arc.ArchiveFloat(&fadeIn); arc.ArchiveFloat(&fadeDelay); arc.ArchiveFloat(&maxAlpha); arc.ArchiveInteger(&lastSpawnTime); arc.ArchiveSafePointer(&owner); } void SmokeGrenade::setOwner(Sentient *other) { owner = other; } Sentient *SmokeGrenade::getOwner() const { return owner; }