Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/StarDamageManager.hpp
blob: c6ba24556e11275848bdb94cbfc5540f54da3878 (plain)
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;
};

}