summaryrefslogtreecommitdiffstats
path: root/src/weapons/Weapon.cpp
blob: 290b9179d70d5b32f9ef4ddde432874e8f0cc0ad (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "common.h"
#include "patcher.h"
#include "Weapon.h"
#include "Timer.h"
#include "WeaponInfo.h"
#include "Ped.h"
#include "World.h"

WRAPPER void CWeapon::ShutdownWeapons(void) { EAXJMP(0x55C2F0); }
WRAPPER void CWeapon::UpdateWeapons(void) { EAXJMP(0x55C310); }
WRAPPER bool CWeapon::Fire(CEntity*, CVector*) { EAXJMP(0x55C380); }
WRAPPER void CWeapon::FireFromCar(CAutomobile *car, bool left) { EAXJMP(0x55C940); }
WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, float) { EAXJMP(0x55F770); }
WRAPPER void CWeapon::Update(int32 audioEntity) { EAXJMP(0x563A10); }
WRAPPER void CWeapon::DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end) { EAXJMP(0x563200); }
WRAPPER void CWeapon::InitialiseWeapons(void) { EAXJMP(0x55C2D0); }
WRAPPER void FireOneInstantHitRound(CVector* shotSource, CVector* shotTarget, int32 damage) { EAXJMP(0x563B00); }
WRAPPER void CWeapon::BlowUpExplosiveThings(CEntity* pEntity) { EAXJMP(0x564A60); }

void
CWeapon::Initialise(eWeaponType type, int ammo)
{
	m_eWeaponType = type;
	m_eWeaponState = WEAPONSTATE_READY;
	if (ammo > 99999)
		m_nAmmoTotal = 99999;
	else
		m_nAmmoTotal = ammo;
	m_nAmmoInClip = 0;
	Reload();
	m_nTimer = 0;
}

void
CWeapon::Reload(void)
{
	if (m_nAmmoTotal == 0)
		return;

	CWeaponInfo *info = CWeaponInfo::GetWeaponInfo(m_eWeaponType);

	if (m_nAmmoTotal >= info->m_nAmountofAmmunition)
		m_nAmmoInClip = info->m_nAmountofAmmunition;
	else
		m_nAmmoInClip = m_nAmmoTotal;
}

bool
CWeapon::IsType2Handed(void)
{
	return m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType <= WEAPONTYPE_FLAMETHROWER && m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER;
}

bool
CWeapon::IsTypeMelee(void)
{
	return m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT;
}

bool
CWeapon::HitsGround(CEntity *holder, CVector *firePos, CEntity *aimingTo)
{
	if (!holder->IsPed() || !((CPed*)holder)->m_pSeekTarget)
		return false;

	CWeaponInfo *ourType = CWeaponInfo::GetWeaponInfo(m_eWeaponType);
	CVector adjustedOffset = ourType->m_vecFireOffset;
	adjustedOffset.z += 0.6f;

	CVector point1, point2;
	CEntity *foundEnt = nil;
	CColPoint foundCol;

	if (firePos)
		point1 = *firePos;
	else
		point1 = holder->GetMatrix() * adjustedOffset;

	CEntity *aimEntity = aimingTo ? aimingTo : ((CPed*)holder)->m_pSeekTarget;
	point2 = aimEntity->GetPosition();
	point2.z += 0.6f;

	CWorld::ProcessLineOfSight(point1, point2, foundCol, foundEnt, true, false, false, false, false, false, false);
	if (foundEnt && foundEnt->IsBuilding()) {
		// That was supposed to be Magnitude, according to leftover code in assembly
		float diff = (foundCol.point.z - point1.z);
		if (diff < 0.0f && diff > -3.0f)
			return true;
	}

	return false;
}

bool
CWeapon::HasWeaponAmmoToBeUsed(void)
{
	switch (m_eWeaponType) {
		case WEAPONTYPE_UNARMED:
		case WEAPONTYPE_BASEBALLBAT:
			return true;
		default:
			return m_nAmmoTotal != 0;
	}
}

STARTPATCHES
	InjectHook(0x55C330, &CWeapon::Initialise, PATCH_JUMP);
	InjectHook(0x5639D0, &CWeapon::Reload, PATCH_JUMP);
	InjectHook(0x564890, &CWeapon::HitsGround, PATCH_JUMP);
ENDPATCHES