-
Notifications
You must be signed in to change notification settings - Fork 0
/
cPlayer.h
424 lines (361 loc) · 20.2 KB
/
cPlayer.h
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
///////////////////////////////////////////////////////
//*-------------------------------------------------*//
//| Part of Project One (https://www.maus-games.at) |//
//*-------------------------------------------------*//
//| Copyright (c) 2010 Martin Mauersics |//
//| Released under the zlib License |//
//*-------------------------------------------------*//
///////////////////////////////////////////////////////
#pragma once
#ifndef _P1_GUARD_PLAYER_H_
#define _P1_GUARD_PLAYER_H_
// TODO 4: add constant for default direction (intro, outro)
// TODO 3: all parts of player-rendering should be batched for multiplayer
// TODO 3: render wind, bubble, etc. in group for multiplayer
// TODO 3: add in-game hint for roll-cooldown end ((just) acoustic)
// TODO 4: PLAYER_FEEL_TIME_SHIELD still used ?
// TODO 3: large part of all sub-objects are constantly added and removed from glow, should be permanent (resurrect<>kill), and controlled with SetEnabled, also for tracker and P1
// ****************************************************************
// player definitions
#define PLAYER_EQUIP_WEAPONS (EQUIP_WEAPONS) // number of weapons a player can carry
#define PLAYER_EQUIP_SUPPORTS (EQUIP_SUPPORTS) //
#define PLAYER_LIVES (LIVES) //
#define PLAYER_COLLISION_MIN (0.2f) //
#define PLAYER_SIZE_FACTOR (1.15f) //
#define PLAYER_SIZE_FACTOR_EXT (1.15f * m_fScale) //
#define PLAYER_AREA_FACTOR (1.06f) //
#define PLAYER_RANGE_SIZE (1.04f) //
#define PLAYER_WIND_SIZE (4.5f) //
#define PLAYER_BUBBLE_SIZE (4.8f) //
#define PLAYER_ROLL_SPEED (0.4f) //
#define PLAYER_ROLL_COOLDOWN (FRAMERATE_MAX) // (ship is vulnerable for a single frame)
#define PLAYER_FEEL_TIME (3.0f) //
#define PLAYER_FEEL_TIME_CONTINUE (5.0f) //
#define PLAYER_FEEL_TIME_REPAIR (5.0f) //
#define PLAYER_FEEL_TIME_COOP (0.15f) //
#define PLAYER_FEEL_TIME_SHIELD (10.0f) //
#define PLAYER_IGNORE_TIME (1.1f) //
#define PLAYER_INTERRUPT (0.3f) //
#define PLAYER_DESATURATE (1.2f) //
#define PLAYER_DESATURATE_FRAGMENT (1.8f) //
#define PLAYER_SHIP_ATK (0u) //
#define PLAYER_SHIP_DEF (1u) //
#define PLAYER_SHIP_P1 (2u) //
#define PLAYER_NO_ROLL (0xFFu) //
#define PLAYER_NO_FEEL (-100.0f) //
#define PLAYER_NO_IGNORE (-100.0f) //
#define PLAYER_ACTION_SHOOT(i,j) ((i) * WEAPON_MODES + (j))
#define PLAYER_ACTION_SHOOT_0 (PLAYER_ACTION_SHOOT(0u, 0u))
#define PLAYER_ACTION_TURN_LEFT (PLAYER_EQUIP_WEAPONS * WEAPON_MODES)
#define PLAYER_ACTION_TURN_RIGHT (PLAYER_EQUIP_WEAPONS * WEAPON_MODES + 1u)
#define PLAYER_ACTION_ROLL (PLAYER_EQUIP_WEAPONS * WEAPON_MODES) // TODO 1: not used
#define PLAYER_ACTION_SHOOT_UP (PLAYER_EQUIP_WEAPONS * WEAPON_MODES + 2u)
#define PLAYER_ACTION_SHOOT_LEFT (PLAYER_EQUIP_WEAPONS * WEAPON_MODES + 3u)
#define PLAYER_ACTION_SHOOT_DOWN (PLAYER_EQUIP_WEAPONS * WEAPON_MODES + 4u)
#define PLAYER_ACTION_SHOOT_RIGHT (PLAYER_EQUIP_WEAPONS * WEAPON_MODES + 5u)
#define PLAYER_ACTION_RAPID_FIRE (PLAYER_EQUIP_WEAPONS * WEAPON_MODES + 7u)
#define PLAYER_ACTION_CHANGE_SPEED (PLAYER_EQUIP_WEAPONS * WEAPON_MODES + 8u)
#define PLAYER_AREA_DEFAULT (coreVector4(-FOREGROUND_AREA, FOREGROUND_AREA) * PLAYER_AREA_FACTOR)
//STATIC_ASSERT(PLAYER_INTERRUPT > (1.0f / PLAYER_ROLL_SPEED))
enum ePlayerStatus : coreUint32
{
PLAYER_STATUS_DEAD = 0x0001u, // completely removed from the game
PLAYER_STATUS_SHIELDED = 0x0002u, //
PLAYER_STATUS_GHOST = 0x0004u, //
PLAYER_STATUS_INVINCIBLE = 0x0008u, //
PLAYER_STATUS_INVINCIBLE_2 = 0x0010u, //
PLAYER_STATUS_HEALER = 0x0020u, //
PLAYER_STATUS_TOP = 0x0040u, //
PLAYER_STATUS_KEEP_RANGE = 0x0080u, // TODO 1: still used ?
PLAYER_STATUS_GYRO = 0x0100u, //
PLAYER_STATUS_ARRANGE = 0x0200u, //
PLAYER_STATUS_WEAK_BACK = 0x0400u, //
PLAYER_STATUS_REPAIRED = 0x0800u, //
PLAYER_STATUS_RAPID_FIRE = 0x1000u, //
PLAYER_STATUS_NO_INPUT_MOVE = 0x2000u, // disable player movement (user controls only)
PLAYER_STATUS_NO_INPUT_SHOOT = 0x4000u, // disable player weapons
PLAYER_STATUS_NO_INPUT_ROLL = 0x8000u, //
PLAYER_STATUS_NO_INPUT_TURN = 0x10000u, //
PLAYER_STATUS_NO_INPUT_RAPID = 0x20000u, //
PLAYER_STATUS_NO_INPUT_ALL = PLAYER_STATUS_NO_INPUT_MOVE | PLAYER_STATUS_NO_INPUT_SHOOT | PLAYER_STATUS_NO_INPUT_ROLL | PLAYER_STATUS_NO_INPUT_TURN | PLAYER_STATUS_NO_INPUT_RAPID
};
enum ePlayerTest : coreUint8
{
PLAYER_TEST_NORMAL = 0x01u, //
PLAYER_TEST_ROLL = 0x02u, //
PLAYER_TEST_FEEL = 0x04u, //
PLAYER_TEST_IGNORE = 0x08u, //
PLAYER_TEST_ALL = PLAYER_TEST_NORMAL | PLAYER_TEST_ROLL | PLAYER_TEST_FEEL | PLAYER_TEST_IGNORE
};
ENABLE_BITWISE(ePlayerTest)
// ****************************************************************
// player entity class
class cPlayer final : public cShip
{
private:
//
struct sRayData final
{
coreUint32 iFrame; //
coreVector2 vPosition; //
coreVector2 vDirection; //
};
private:
cWeapon* m_apWeapon[PLAYER_EQUIP_WEAPONS]; // main weapon objects (bullet factories, should never be NULL)
const sGameInput* m_pInput; // pointer to associated input set (should never be NULL)
coreVector4 m_vArea; //
coreVector2 m_vForce; //
coreFloat m_fScale; //
coreFloat m_fThrust; //
coreFloat m_fTilt; //
coreProtect<coreFloat> m_fMoveSpeed; //
coreProtect<coreFloat> m_fShootSpeed; //
coreFloat m_fAnimSpeed; // (also affects feel and ignore duration)
coreFlow m_fRollTime; //
coreFlow m_fFeelTime; //
coreFlow m_fIgnoreTime; //
coreUint8 m_iRollDir; //
coreUint8 m_iFeelType; //
coreUint8 m_iIgnoreType; //
coreFlow m_fInterrupt; //
coreFlow m_fLightningTime; //
coreFloat m_fLightningAngle; //
coreFlow m_fDesaturate; //
coreProtect<coreInt32> m_iMaxShield; //
coreProtect<coreInt32> m_iCurShield; //
coreProtect<coreInt32> m_iPreShield; //
cDataTable m_DataTable; //
cScoreTable m_ScoreTable; //
coreProgramPtr m_pNormalProgram; //
coreProgramPtr m_pDarkProgram; //
coreFlow m_fAnimation; //
coreUint16 m_iLook; //
coreFloat m_fRangeScale; //
coreVector3 m_vMenuColor; //
coreVector3 m_vLedColor; //
coreVector2 m_vOldDir; //
coreVector2 m_vSmoothOri; //
coreFloat m_fSmoothThrust; //
coreFloat m_fSmoothTilt; //
coreFlow m_fRangeValue; //
coreFlow m_fArrowValue; //
coreFlow m_fBubbleValue; //
coreFlow m_fCircleValue; //
coreFlow m_fFlashValue; //
coreFlow m_fBoost; //
coreUint8 m_iLastMove; //
coreUint8 m_iLastHold; //
coreUint8 m_iShootToggle; //
coreObject3D m_Dot; //
coreObject3D m_Range; //
coreObject3D m_Arrow; //
coreObject3D m_Wind; //
coreObject3D m_Bubble; //
coreObject3D m_aShield[2]; //
coreObject3D m_Circle; //
coreObject3D m_Flash; //
coreObject3D m_Exhaust; //
coreMap<const coreObject3D*, coreUint32> m_aiCollision; //
coreMap<const coreObject3D*, sRayData> m_aRayData; //
coreBool m_bWasDamaged;
coreBool m_bGiveUp;
public:
cPlayer()noexcept;
~cPlayer()final;
DISABLE_COPY(cPlayer)
// configure the player
void Configure (const coreUintW iShipType);
void EquipShield (const coreInt32 iShield);
void EquipWeapon (const coreUintW iIndex, const coreInt32 iID);
void EquipSupport(const coreUintW iIndex, const coreInt32 iID);
// render and move the player
void Render ()final;
void RenderBefore();
void RenderMiddle();
void RenderAfter ();
void Move ()final;
// reduce current health
coreInt32 TakeDamage(const coreInt32 iDamage, const coreUint8 iElement, const coreVector2 vImpact);
//
void HealHealth(const coreUint8 iHealth);
void HealShield(const coreUint8 iShield);
// control life and death
void Resurrect();
void Kill (const coreBool bAnimated);
//
void ShowArrow (const coreUint8 iType);
void ShowCircle();
void ShowFlash (const coreUint8 iType);
//
void StartRolling (const coreVector2 vDirection);
void StartRolling ();
void EndRolling ();
void StartFeeling (const coreFloat fTime, const coreUint8 iType);
void EndFeeling ();
void StartIgnoring(const coreUint8 iType);
void EndIgnoring ();
//
inline void ActivateNormalShading() {this->DefineProgram(m_pNormalProgram);}
inline void ActivateDarkShading () {this->DefineProgram(m_pDarkProgram);}
//
void TurnIntoEnemy ();
void TurnIntoPlayer();
//
inline coreBool IsNormal ()const {return (!this->IsRolling() && !this->IsFeeling() && !this->IsIgnoring());}
inline coreBool IsRolling ()const {return false;}
inline coreBool IsRolling2 ()const {return (m_iRollDir != PLAYER_NO_ROLL);}
inline coreBool IsFeeling ()const {return (m_fFeelTime > PLAYER_NO_FEEL);}
inline coreBool IsIgnoring ()const {return (m_fIgnoreTime > PLAYER_NO_IGNORE);}
inline coreBool IsDarkShading()const {return (this->GetProgram().GetHandle() == m_pDarkProgram.GetHandle());}
inline coreBool IsEnemyLook ()const {return (m_apWeapon[0]->GetID() == cEnemyWeapon::ID);}
//
void EnableRange ();
void DisableRange ();
void EnableArrow ();
void DisableArrow ();
void EnableWind (const coreVector2 vDirection = coreVector2(0.0f,0.0f));
void DisableWind ();
void EnableBubble ();
void DisableBubble ();
void EnableShield ();
void DisableShield ();
void EnableCircle ();
void DisableCircle ();
void EnableFlash ();
void DisableFlash ();
void EnableExhaust ();
void DisableExhaust();
//
void OverrideColor(const coreVector3 vEnergyColor, const coreVector3 vMenuColor, const coreVector3 vLedColor);
//
inline const coreModelPtr& GetRangeModel ()const {return m_Range.GetModel();}
inline const coreFloat& GetRangeScale ()const {return m_fRangeScale;}
inline coreVector3 GetEnergyColor()const {return m_Range.GetColor3() * (1.0f/1.1f);}
inline const coreVector3& GetMenuColor ()const {return m_vMenuColor;}
inline const coreVector3& GetLedColor ()const {return m_vLedColor;}
//
coreBool TestCollisionPrecise(const coreObject3D* pObject, coreVector3* OUTPUT pvIntersection, coreBool* OUTPUT pbFirstHit);
coreBool TestCollisionPrecise(const coreVector2 vRayPos, const coreVector2 vRayDir, const coreObject3D* pRef, coreFloat* OUTPUT pfHitDistance, coreUint8* OUTPUT piHitCount, coreBool* OUTPUT pbFirstHit);
//
inline void ApplyForce (const coreVector2 vForce) {m_vForce += vForce; this->SetPosition(coreVector3(m_vOldPos, 0.0f));}
inline void ApplyForceTimed(const coreVector2 vForce) {m_vForce += vForce * TIME;}
//
coreVector2 CalcMove ()const;
coreFloat CalcMoveSpeed()const;
//
inline cWeapon* GetWeapon (const coreUintW iIndex)const {ASSERT((iIndex < PLAYER_EQUIP_WEAPONS) && m_apWeapon[iIndex]) return m_apWeapon[iIndex];}
inline cDataTable* GetDataTable () {return &m_DataTable;}
inline cScoreTable* GetScoreTable() {return &m_ScoreTable;}
// set object properties
inline void SetInput (const sGameInput* pInput) {m_pInput = pInput;}
inline void SetArea (const coreVector4 vArea) {m_vArea = vArea; ASSERT(vArea.xy() < vArea.zw())}
inline void SetForce (const coreVector2 vForce) {m_vForce = vForce;}
inline void SetScale (const coreFloat fScale) {m_fScale = fScale;}
inline void SetThrust (const coreFloat fThrust) {m_fThrust = fThrust;}
inline void SetTilt (const coreFloat fTilt) {m_fTilt = fTilt;}
inline void SetMoveSpeed (const coreFloat fMoveSpeed) {m_fMoveSpeed = fMoveSpeed;}
inline void SetShootSpeed (const coreFloat fShootSpeed) {m_fShootSpeed = fShootSpeed;}
inline void SetAnimSpeed (const coreFloat fAnimSpeed) {m_fAnimSpeed = fAnimSpeed;}
inline void SetInterrupt (const coreFloat fInterrupt) {m_fInterrupt = fInterrupt;}
inline void SetDesaturate (const coreFloat fDesaturate) {m_fDesaturate = fDesaturate;}
inline void SetMaxShield (const coreInt32 iMaxShield) {m_iMaxShield = iMaxShield;}
inline void SetCurShield (const coreInt32 iCurShield) {m_iCurShield = iCurShield;}
inline void SetCurShieldPct(const coreFloat fCurShieldPct) {m_iCurShield = F_TO_SI(fCurShieldPct * I_TO_F(m_iMaxShield)); ASSERT((fCurShieldPct >= 0.0f) && (fCurShieldPct <= 1.0f))}
// get object properties
inline const sGameInput* GetInput ()const {ASSERT(m_pInput) return m_pInput;}
inline const coreVector4& GetArea ()const {return m_vArea;}
inline const coreVector2& GetForce ()const {return m_vForce;}
inline const coreFloat& GetScale ()const {return m_fScale;}
inline const coreFloat& GetTilt ()const {return m_fTilt;}
inline coreFloat GetMoveSpeed ()const {return m_fMoveSpeed;}
inline coreFloat GetShootSpeed ()const {return m_fShootSpeed;}
inline const coreFloat& GetAnimSpeed ()const {return m_fAnimSpeed;}
inline const coreFloat& GetInterrupt ()const {return m_fInterrupt;}
inline const coreFloat& GetDesaturate ()const {return m_fDesaturate;}
inline coreInt32 GetMaxShield ()const {return m_iMaxShield;}
inline coreInt32 GetCurShield ()const {return m_iCurShield;}
inline coreFloat GetCurShieldPct()const {return I_TO_F(m_iCurShield) / I_TO_F(m_iMaxShield);} // # normal division
inline coreInt32 GetPreShield ()const {return m_iPreShield;}
inline coreFloat GetPreShieldPct()const {return I_TO_F(m_iPreShield) / I_TO_F(m_iMaxShield);} // # normal division
//
template <typename F> static FORCE_INLINE void TestCollision(const ePlayerTest eTest, const coreInt32 iType, F&& nCallback); // [](cPlayer* OUTPUT pPlayer, coreObject3D* OUTPUT pObject, const coreVector3 vIntersection, const coreBool bFirstHit) -> void
template <typename F> static FORCE_INLINE void TestCollision(const ePlayerTest eTest, coreObject3D* OUTPUT pObject, F&& nCallback); // [](cPlayer* OUTPUT pPlayer, coreObject3D* OUTPUT pObject, const coreVector3 vIntersection, const coreBool bFirstHit) -> void
template <typename F> static FORCE_INLINE void TestCollision(const ePlayerTest eTest, const coreVector2 vRayPos, const coreVector2 vRayDir, const coreObject3D* pRef, F&& nCallback); // [](cPlayer* OUTPUT pPlayer, const coreFloat* pfHitDistance, const coreUint8 iHitCount, const coreBool bFirstHit) -> void
void SetPosition (const coreVector3 vPosition);
void SetDirection(const coreVector3 vDirection);
// coreObject3D::Move in teleport
inline coreBool ReachedHealth (const coreInt32 iHealth)const {UNREACHABLE return false;}
inline coreBool ReachedHealthPct(const coreFloat fHealthPct)const {UNREACHABLE return false;}
inline const coreBool& WasDamaged()const {return m_bWasDamaged;}
private:
//
coreBool __NewCollision(const coreObject3D* pObject);
sRayData __NewRayData (const coreVector2 vRayPos, const coreVector2 vRayDir, const coreObject3D* pRef);
void __UpdateCollisions();
//
coreBool __CheckPlayerTest(const ePlayerTest eTest)const;
};
// ****************************************************************
//
template <typename F> FORCE_INLINE void cPlayer::TestCollision(const ePlayerTest eTest, const coreInt32 iType, F&& nCallback)
{
//
Core::Manager::Object->TestCollision(TYPE_PLAYER, iType, [&](cPlayer* OUTPUT pPlayer, coreObject3D* OUTPUT pObject, const coreVector3 vIntersection, const coreBool bFirstHit)
{
//
if(pPlayer->__CheckPlayerTest(eTest))
{
//
coreVector3 vNewIntersection;
coreBool bNewFirstHit;
if(pPlayer->TestCollisionPrecise(pObject, &vNewIntersection, &bNewFirstHit))
{
nCallback(pPlayer, d_cast<typename TRAIT_ARG_TYPE(F, 1u)>(pObject), vNewIntersection, bNewFirstHit);
}
}
});
}
// ****************************************************************
//
template <typename F> FORCE_INLINE void cPlayer::TestCollision(const ePlayerTest eTest, coreObject3D* OUTPUT pObject, F&& nCallback)
{
//
Core::Manager::Object->TestCollision(TYPE_PLAYER, pObject, [&](cPlayer* OUTPUT pPlayer, coreObject3D* OUTPUT pObject, const coreVector3 vIntersection, const coreBool bFirstHit)
{
//
if(pPlayer->__CheckPlayerTest(eTest))
{
//
coreVector3 vNewIntersection;
coreBool bNewFirstHit;
if(pPlayer->TestCollisionPrecise(pObject, &vNewIntersection, &bNewFirstHit))
{
nCallback(pPlayer, d_cast<typename TRAIT_ARG_TYPE(F, 1u)>(pObject), vNewIntersection, bNewFirstHit);
}
}
});
}
// ****************************************************************
//
template <typename F> FORCE_INLINE void cPlayer::TestCollision(const ePlayerTest eTest, const coreVector2 vRayPos, const coreVector2 vRayDir, const coreObject3D* pRef, F&& nCallback)
{
//
const coreList<coreObject3D*>& oPlayerList = Core::Manager::Object->GetObjectList(TYPE_PLAYER);
FOR_EACH(it, oPlayerList)
{
//
cPlayer* pPlayer = d_cast<cPlayer*>(*it);
if(pPlayer && pPlayer->__CheckPlayerTest(eTest))
{
//
coreFloat fNewHitDistance;
coreUint8 iNewHitCount;
coreBool bNewFirstHit;
if(pPlayer->TestCollisionPrecise(vRayPos, vRayDir, pRef, &fNewHitDistance, &iNewHitCount, &bNewFirstHit))
{
nCallback(pPlayer, &fNewHitDistance, iNewHitCount, bNewFirstHit);
}
}
}
}
#endif // _P1_GUARD_PLAYER_H_