openmohaa/code/fgame/windows.cpp
2024-11-05 22:03:43 +01:00

190 lines
4.5 KiB
C++

/*
===========================================================================
Copyright (C) 2015 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
===========================================================================
*/
// windows.cpp: Window class
//
#include "g_phys.h"
#include "windows.h"
#include "game.h"
Event EV_Window_Setup
(
"_Windowsetup",
EV_CODEONLY,
NULL,
NULL,
"Does the post spawn setup of the Window"
);
Event EV_Window_SetDebris
(
"debristype",
EV_DEFAULT,
"i",
"type",
"Sets the debris type of the Window"
);
CLASS_DECLARATION(Entity, WindowObject, "func_window") {
{&EV_Window_Setup, &WindowObject::WindowSetup },
{&EV_Damage, &WindowObject::WindowDamaged },
{&EV_Killed, &WindowObject::WindowKilled },
{&EV_Window_SetDebris, &WindowObject::WindowDebrisType},
{NULL, NULL }
};
WindowObject::WindowObject()
{
if (LoadingSavegame) {
return;
}
edict->s.eType = ET_GENERAL;
health = 250;
max_health = health;
deadflag = 0;
takedamage = DAMAGE_YES;
m_iDebrisType = WINDOW_GLASS;
PostEvent(EV_Window_Setup, EV_POSTSPAWN);
}
void WindowObject::Archive(Archiver& arc)
{
Entity::Archive(arc);
arc.ArchiveInteger(&m_iDebrisType);
arc.ArchiveString(&m_sBrokenModel);
}
void WindowObject::WindowSetup(Event *ev)
{
Entity *pEnt;
setMoveType(MOVETYPE_NONE);
setSolidType(SOLID_BSP);
setContents(CONTENTS_TRIGGER);
if (Target().length()) {
// If a target is defined,
// find it and set the model from it
pEnt = (Entity *)G_FindTarget(NULL, Target());
if (pEnt) {
m_sBrokenModel = pEnt->model;
// Don't keep the original entity
pEnt->PostEvent(EV_Remove, 0);
}
}
}
void WindowObject::WindowDebrisType(Event *ev)
{
m_iDebrisType = ev->GetInteger(1);
}
void WindowObject::WindowDamaged(Event *ev)
{
int iMeansOfDeath;
int iDamage;
Vector vRight;
Vector vForward;
Vector vDir;
Event *event;
if (!takedamage) {
return;
}
iDamage = ev->GetInteger(2);
iMeansOfDeath = ev->GetInteger(9);
if (iMeansOfDeath == MOD_BASH) {
// double damage for bash
iDamage *= 2;
} else if (iMeansOfDeath == MOD_EXPLOSION) {
// instant break
iDamage *= 10;
}
health -= iDamage;
if (health <= 0.0f) {
event = new Event(EV_Killed);
event->AddEntity(ev->GetEntity(1));
event->AddInteger(ev->GetInteger(2));
event->AddEntity(ev->GetEntity(3));
ProcessEvent(event);
}
}
void WindowObject::WindowKilled(Event *ev)
{
Vector vCenter;
setSolidType(SOLID_NOT);
hideModel();
takedamage = DAMAGE_NO;
vCenter = (mins + maxs) * 0.5;
vCenter += origin;
gi.SetBroadcastVisible(vCenter, vCenter);
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_WINDOW_DEBRIS));
gi.MSG_WriteCoord(vCenter[0]);
gi.MSG_WriteCoord(vCenter[1]);
gi.MSG_WriteCoord(vCenter[2]);
gi.MSG_WriteByte(m_iDebrisType);
gi.MSG_EndCGM();
if (m_sBrokenModel.length()) {
Entity *ent = new Entity;
ent->takedamage = DAMAGE_NO;
ent->setModel(m_sBrokenModel);
ent->setMoveType(MOVETYPE_NONE);
ent->setSolidType(SOLID_BSP);
setModel(m_sBrokenModel);
if (spawnflags & WINDOW_BROKEN_BLOCK) {
ent->setContents(CONTENTS_MONSTERCLIP | CONTENTS_PLAYERCLIP);
} else {
ent->setContents(CONTENTS_SHOOTONLY);
}
ent->setOrigin(origin);
ent->showModel();
}
deadflag = DEAD_DEAD;
// remove the window
PostEvent(EV_Remove, 0);
}