summaryrefslogtreecommitdiffstats
path: root/src/vehicles/DamageManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vehicles/DamageManager.cpp')
-rw-r--r--src/vehicles/DamageManager.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/vehicles/DamageManager.cpp b/src/vehicles/DamageManager.cpp
new file mode 100644
index 00000000..1a7f25ed
--- /dev/null
+++ b/src/vehicles/DamageManager.cpp
@@ -0,0 +1,243 @@
+#include "common.h"
+#include "patcher.h"
+#include "General.h"
+#include "DamageManager.h"
+
+
+float G_aComponentDamage[] = { 2.5f, 1.25f, 3.2f, 1.4f, 2.5f, 2.8f, 0.5f };
+
+void
+CDamageManager::ResetDamageStatus(void)
+{
+ memset(this, 0, sizeof(*this));
+}
+
+void
+CDamageManager::FuckCarCompletely(void)
+{
+ int i;
+
+ m_wheelStatus[0] = 2;
+ // wheels 1-3 not reset?
+
+ m_doorStatus[0] = 3;
+ m_doorStatus[1] = 3;
+ m_doorStatus[2] = 3;
+ m_doorStatus[3] = 3;
+ m_doorStatus[4] = 3;
+ m_doorStatus[5] = 3;
+
+ for(i = 0; i < 3; i++){
+#ifdef FIX_BUGS
+ ProgressPanelDamage(VEHBUMPER_FRONT);
+ ProgressPanelDamage(VEHBUMPER_REAR);
+#else
+ // this can't be right
+ ProgressPanelDamage(COMPONENT_BUMPER_FRONT);
+ ProgressPanelDamage(COMPONENT_BUMPER_REAR);
+#endif
+ }
+ // Why set to no damage?
+ m_lightStatus = 0;
+ m_panelStatus = 0;
+ SetEngineStatus(250);
+}
+
+bool
+CDamageManager::ApplyDamage(tComponent component, float damage, float unused)
+{
+ tComponentGroup group;
+ uint8 subComp;
+
+ GetComponentGroup(component, &group, &subComp);
+ damage *= G_aComponentDamage[group];
+ if(damage > 150.0f){
+ switch(group){
+ case COMPGROUP_WHEEL:
+ ProgressWheelDamage(subComp);
+ break;
+ case COMPGROUP_DOOR:
+ case COMPGROUP_BOOT:
+ ProgressDoorDamage(subComp);
+ break;
+ case COMPGROUP_BONNET:
+ if(damage > 220.0f)
+ ProgressEngineDamage();
+ ProgressDoorDamage(subComp);
+ break;
+ case COMPGROUP_PANEL:
+ // so windscreen is a light?
+ SetLightStatus((eLights)subComp, 1);
+ // fall through
+ case COMPGROUP_BUMPER:
+ if(damage > 220.0f &&
+ (component == COMPONENT_PANEL_FRONT_LEFT ||
+ component == COMPONENT_PANEL_FRONT_RIGHT ||
+ component == COMPONENT_PANEL_WINDSCREEN))
+ ProgressEngineDamage();
+ ProgressPanelDamage(subComp);
+ break;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool
+CDamageManager::GetComponentGroup(tComponent component, tComponentGroup *componentGroup, uint8 *subComp)
+{
+ *subComp = -2; // ??
+
+ // This is done very strangely in the game, maybe an optimized switch?
+ if(component >= COMPONENT_PANEL_FRONT_LEFT){
+ if(component >= COMPONENT_BUMPER_FRONT)
+ *componentGroup = COMPGROUP_BUMPER;
+ else
+ *componentGroup = COMPGROUP_PANEL;
+ *subComp = component - COMPONENT_PANEL_FRONT_LEFT;
+ return true;
+ }else if(component >= COMPONENT_DOOR_BONNET){
+ if(component == COMPONENT_DOOR_BONNET)
+ *componentGroup = COMPGROUP_BONNET;
+ else if(component == COMPONENT_DOOR_BOOT)
+ *componentGroup = COMPGROUP_BOOT;
+ else
+ *componentGroup = COMPGROUP_DOOR;
+ *subComp = component - COMPONENT_DOOR_BONNET;
+ return true;
+ }else if(component >= COMPONENT_WHEEL_FRONT_LEFT){
+ *componentGroup = COMPGROUP_WHEEL;
+ *subComp = component - COMPONENT_WHEEL_FRONT_LEFT;
+ return true;
+ }else if(component >= COMPONENT_DEFAULT){
+ *componentGroup = COMPGROUP_DEFAULT;
+ *subComp = component - COMPONENT_DEFAULT;
+ return true;
+ }else
+ return false;
+}
+
+void
+CDamageManager::SetDoorStatus(int32 door, uint32 status)
+{
+ m_doorStatus[door] = status;
+}
+
+int32
+CDamageManager::GetDoorStatus(int32 door)
+{
+ return m_doorStatus[door];
+}
+
+bool
+CDamageManager::ProgressDoorDamage(uint8 door)
+{
+ int status = GetDoorStatus(door);
+ if(status == 3)
+ return false;
+ SetDoorStatus(door, status+1);
+ return true;
+}
+
+void
+CDamageManager::SetPanelStatus(int32 panel, uint32 status)
+{
+ m_panelStatus = dpb(status, panel*4, 4, m_panelStatus);
+}
+
+int32
+CDamageManager::GetPanelStatus(int32 panel)
+{
+ return ldb(panel*4, 4, m_panelStatus);
+}
+
+bool
+CDamageManager::ProgressPanelDamage(uint8 panel)
+{
+ int status = GetPanelStatus(panel);
+ if(status == 3)
+ return false;
+ SetPanelStatus(panel, status+1);
+ return true;
+}
+
+void
+CDamageManager::SetLightStatus(eLights light, uint32 status)
+{
+ m_lightStatus = dpb(status, light*2, 2, m_lightStatus);
+}
+
+int32
+CDamageManager::GetLightStatus(eLights light)
+{
+ return ldb(light*2, 2, m_lightStatus);
+}
+
+void
+CDamageManager::SetWheelStatus(int32 wheel, uint32 status)
+{
+ m_wheelStatus[wheel] = status;
+}
+
+int32
+CDamageManager::GetWheelStatus(int32 wheel)
+{
+ return m_wheelStatus[wheel];
+}
+
+bool
+CDamageManager::ProgressWheelDamage(uint8 wheel)
+{
+ int status = GetWheelStatus(wheel);
+ if(status == 3)
+ return false;
+ SetWheelStatus(wheel, status+1);
+ return true;
+}
+
+void
+CDamageManager::SetEngineStatus(uint32 status)
+{
+ if(status > 250)
+ m_engineStatus = 250;
+ else
+ m_engineStatus = status;
+}
+
+int32
+CDamageManager::GetEngineStatus(void)
+{
+ return m_engineStatus;
+}
+
+bool
+CDamageManager::ProgressEngineDamage(void)
+{
+ int status = GetEngineStatus();
+ int newstatus = status + 32 + (CGeneral::GetRandomNumber() & 0x1F);
+ if(status < 225 && newstatus > 224)
+ newstatus = 224;
+ SetEngineStatus(newstatus);
+ return true;
+}
+
+STARTPATCHES
+ InjectHook(0x545850, &CDamageManager::ResetDamageStatus, PATCH_JUMP);
+ InjectHook(0x545B70, &CDamageManager::FuckCarCompletely, PATCH_JUMP);
+ InjectHook(0x545790, &CDamageManager::GetComponentGroup, PATCH_JUMP);
+ InjectHook(0x545A80, &CDamageManager::ApplyDamage, PATCH_JUMP);
+ InjectHook(0x545920, &CDamageManager::SetDoorStatus, PATCH_JUMP);
+ InjectHook(0x545930, &CDamageManager::GetDoorStatus, PATCH_JUMP);
+ InjectHook(0x545970, &CDamageManager::ProgressDoorDamage, PATCH_JUMP);
+ InjectHook(0x5458B0, &CDamageManager::SetPanelStatus, PATCH_JUMP);
+ InjectHook(0x5458E0, (int32 (CDamageManager::*)(int32))&CDamageManager::GetPanelStatus, PATCH_JUMP);
+ InjectHook(0x545A00, &CDamageManager::ProgressPanelDamage, PATCH_JUMP);
+ InjectHook(0x545860, &CDamageManager::SetLightStatus, PATCH_JUMP);
+ InjectHook(0x545890, &CDamageManager::GetLightStatus, PATCH_JUMP);
+ InjectHook(0x545900, &CDamageManager::SetWheelStatus, PATCH_JUMP);
+ InjectHook(0x545910, &CDamageManager::GetWheelStatus, PATCH_JUMP);
+ InjectHook(0x545A40, &CDamageManager::ProgressWheelDamage, PATCH_JUMP);
+ InjectHook(0x545940, &CDamageManager::SetEngineStatus, PATCH_JUMP);
+ InjectHook(0x545960, &CDamageManager::GetEngineStatus, PATCH_JUMP);
+ InjectHook(0x5459B0, &CDamageManager::ProgressEngineDamage, PATCH_JUMP);
+ENDPATCHES