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
|
#pragma once
#include "StarDamage.hpp"
#include "StarDamageTypes.hpp"
namespace Star {
STAR_CLASS(World);
STAR_CLASS(Entity);
STAR_CLASS(DamageManager);
struct RemoteHitRequest {
ConnectionId destinationConnection() const;
EntityId causingEntityId;
EntityId targetEntityId;
DamageRequest damageRequest;
};
DataStream& operator<<(DataStream& ds, RemoteHitRequest const& hitRequest);
DataStream& operator>>(DataStream& ds, RemoteHitRequest& hitRequest);
struct RemoteDamageRequest {
ConnectionId destinationConnection() const;
EntityId causingEntityId;
EntityId targetEntityId;
DamageRequest damageRequest;
};
DataStream& operator<<(DataStream& ds, RemoteDamageRequest const& damageRequest);
DataStream& operator>>(DataStream& ds, RemoteDamageRequest& damageRequest);
struct RemoteDamageNotification {
EntityId sourceEntityId;
DamageNotification damageNotification;
};
DataStream& operator<<(DataStream& ds, RemoteDamageNotification const& damageNotification);
DataStream& operator>>(DataStream& ds, RemoteDamageNotification& damageNotification);
// Right now, handles entity -> entity damage and ensures that no repeat damage
// is applied within the damage cutoff time from the same causing entity.
class DamageManager {
public:
DamageManager(World* world, ConnectionId connectionId);
// Notify entities that they have caused damage, apply damage to master
// entities, produce damage notifications, and run down damage timeouts.
void update(float dt);
// Incoming RemoteHitRequest and RemoteDamageRequest must have the
// destinationConnection equal to the DamageManager's connectionId
void pushRemoteHitRequest(RemoteHitRequest const& remoteHitRequest);
void pushRemoteDamageRequest(RemoteDamageRequest const& remoteDamageRequest);
void pushRemoteDamageNotification(RemoteDamageNotification remoteDamageNotification);
List<RemoteHitRequest> pullRemoteHitRequests();
List<RemoteDamageRequest> pullRemoteDamageRequests();
List<RemoteDamageNotification> pullRemoteDamageNotifications();
// Pending *local* notifications. Sum of all notifications either generated
// locally or recieved.
List<DamageNotification> pullPendingNotifications();
private:
struct EntityDamageEvent {
Variant<EntityId, String> timeoutGroup;
float timeout;
};
// Searches for and queries for hit to any entity within range of the
// damage source. Skips over source.sourceEntityId, if set.
SmallList<pair<EntityId, HitType>, 4> queryHit(DamageSource const& source, EntityId causingId) const;
bool isAuthoritative(EntityPtr const& causingEntity, EntityPtr const& targetEntity);
void addHitRequest(RemoteHitRequest const& remoteHitRequest);
void addDamageRequest(RemoteDamageRequest remoteDamageRequest);
void addDamageNotification(RemoteDamageNotification remoteDamageNotification);
World* m_world;
ConnectionId m_connectionId;
// Maps target entity to all of the recent damage events that entity has
// received, to prevent rapidly repeating damage.
HashMap<EntityId, List<EntityDamageEvent>> m_recentEntityDamages;
List<RemoteHitRequest> m_pendingRemoteHitRequests;
List<RemoteDamageRequest> m_pendingRemoteDamageRequests;
List<RemoteDamageNotification> m_pendingRemoteNotifications;
List<DamageNotification> m_pendingNotifications;
};
}
|