the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#include "stdafx.h"
2#include "net.minecraft.world.entity.h"
3#include "net.minecraft.world.level.h"
4#include "net.minecraft.world.level.tile.h"
5#include "net.minecraft.world.phys.h"
6#include "net.minecraft.world.damagesource.h"
7#include "CombatTracker.h"
8
9CombatTracker::CombatTracker(LivingEntity *mob)
10{
11 this->mob = mob;
12}
13
14CombatTracker::~CombatTracker()
15{
16 for (AUTO_VAR(it,entries.begin()); it != entries.end(); ++it)
17 {
18 delete (*it);
19 }
20}
21
22
23void CombatTracker::prepareForDamage()
24{
25 resetPreparedStatus();
26
27 if (mob->onLadder())
28 {
29 int type = mob->level->getTile(Mth::floor(mob->x), Mth::floor(mob->bb->y0), Mth::floor(mob->z));
30
31 if (type == Tile::ladder->id)
32 {
33 nextLocation = eLocation_LADDER;
34 }
35 else if (type == Tile::vine->id)
36 {
37 nextLocation = eLocation_VINES;
38 }
39 }
40 else if (mob->isInWater())
41 {
42 nextLocation = eLocation_WATER;
43 }
44}
45
46void CombatTracker::recordDamage(DamageSource *source, float health, float damage)
47{
48 recheckStatus();
49 prepareForDamage();
50
51 CombatEntry *entry = new CombatEntry(source, mob->tickCount, health, damage, nextLocation, mob->fallDistance);
52
53 entries.push_back(entry);
54 lastDamageTime = mob->tickCount;
55 takingDamage = true;
56 inCombat |= entry->isCombatRelated();
57}
58
59shared_ptr<ChatPacket> CombatTracker::getDeathMessagePacket()
60{
61 if (entries.size() == 0) return shared_ptr<ChatPacket>(new ChatPacket(mob->getNetworkName()));
62
63 CombatEntry *knockOffEntry = getMostSignificantFall();
64 CombatEntry *killingBlow = entries[entries.size() - 1];
65
66 shared_ptr<ChatPacket> result;
67
68 shared_ptr<Entity> killingEntity = killingBlow->getSource()->getEntity();
69
70 if (knockOffEntry != NULL && killingBlow->getSource()->equals(DamageSource::fall))
71 {
72 shared_ptr<Entity> attackerEntity = knockOffEntry->getSource()->getEntity();
73
74 if (knockOffEntry->getSource()->equals(DamageSource::fall) || knockOffEntry->getSource()->equals(DamageSource::outOfWorld))
75 {
76 ChatPacket::EChatPacketMessage message;
77
78 switch(getFallLocation(knockOffEntry))
79 {
80 case eLocation_GENERIC:
81 message = ChatPacket::e_ChatDeathFellAccidentGeneric;
82 break;
83 case eLocation_LADDER:
84 message = ChatPacket::e_ChatDeathFellAccidentLadder;
85 break;
86 case eLocation_VINES:
87 message = ChatPacket::e_ChatDeathFellAccidentVines;
88 break;
89 case eLocation_WATER:
90 message = ChatPacket::e_ChatDeathFellAccidentWater;
91 break;
92 }
93
94 result = shared_ptr<ChatPacket>(new ChatPacket(mob->getNetworkName(), message));
95 }
96 else if (attackerEntity != NULL && (killingEntity == NULL || attackerEntity != killingEntity))
97 {
98 shared_ptr<ItemInstance> attackerItem = attackerEntity->instanceof(eTYPE_LIVINGENTITY) ? dynamic_pointer_cast<LivingEntity>(attackerEntity)->getCarriedItem() : nullptr;
99
100 if (attackerItem != NULL && attackerItem->hasCustomHoverName())
101 {
102 result = shared_ptr<ChatPacket>(new ChatPacket(mob->getNetworkName(), ChatPacket::e_ChatDeathFellAssistItem, attackerEntity->GetType(), attackerEntity->getNetworkName(), attackerItem->getHoverName()));
103 }
104 else
105 {
106 result = shared_ptr<ChatPacket>(new ChatPacket(mob->getNetworkName(), ChatPacket::e_ChatDeathFellAssist, attackerEntity->GetType(), attackerEntity->getNetworkName()));
107 }
108 }
109 else if (killingEntity != NULL)
110 {
111 shared_ptr<ItemInstance> killerItem = killingEntity->instanceof(eTYPE_LIVINGENTITY) ? dynamic_pointer_cast<LivingEntity>(killingEntity)->getCarriedItem() : nullptr;
112 if (killerItem != NULL && killerItem->hasCustomHoverName())
113 {
114 result = shared_ptr<ChatPacket>(new ChatPacket(mob->getNetworkName(), ChatPacket::e_ChatDeathFellFinishItem, killingEntity->GetType(), killingEntity->getNetworkName(), killerItem->getHoverName()));
115 }
116 else
117 {
118 result = shared_ptr<ChatPacket>(new ChatPacket(mob->getNetworkName(), ChatPacket::e_ChatDeathFellFinish, killingEntity->GetType(), killingEntity->getNetworkName()));
119 }
120 }
121 else
122 {
123 result = shared_ptr<ChatPacket>(new ChatPacket(mob->getNetworkName(), ChatPacket::e_ChatDeathFellKiller));
124 }
125 }
126 else
127 {
128 result = killingBlow->getSource()->getDeathMessagePacket(dynamic_pointer_cast<LivingEntity>(mob->shared_from_this()));
129 }
130
131 return result;
132}
133
134shared_ptr<LivingEntity> CombatTracker::getKiller()
135{
136 shared_ptr<LivingEntity> bestMob = nullptr;
137 shared_ptr<Player> bestPlayer = nullptr;
138 float bestMobDamage = 0;
139 float bestPlayerDamage = 0;
140
141 for (AUTO_VAR(it,entries.begin()); it != entries.end(); ++it)
142 {
143 CombatEntry *entry = *it;
144 if ( entry->getSource() != NULL && entry->getSource()->getEntity() != NULL && entry->getSource()->getEntity()->instanceof(eTYPE_PLAYER) && (bestPlayer == NULL || entry->getDamage() > bestPlayerDamage))
145 {
146 bestPlayerDamage = entry->getDamage();
147 bestPlayer = dynamic_pointer_cast<Player>(entry->getSource()->getEntity());
148 }
149
150 if ( entry->getSource() != NULL && entry->getSource()->getEntity() != NULL && entry->getSource()->getEntity()->instanceof(eTYPE_LIVINGENTITY) && (bestMob == NULL || entry->getDamage() > bestMobDamage))
151 {
152 bestMobDamage = entry->getDamage();
153 bestMob = dynamic_pointer_cast<LivingEntity>(entry->getSource()->getEntity());
154 }
155 }
156
157 if (bestPlayer != NULL && bestPlayerDamage >= bestMobDamage / 3)
158 {
159 return bestPlayer;
160 }
161 else
162 {
163 return bestMob;
164 }
165}
166
167CombatEntry *CombatTracker::getMostSignificantFall()
168{
169 CombatEntry *result = NULL;
170 CombatEntry *alternative = NULL;
171 int altDamage = 0;
172 float bestFall = 0;
173
174 for (int i = 0; i < entries.size(); i++)
175 {
176 CombatEntry *entry = entries.at(i);
177 CombatEntry *previous = i > 0 ? entries.at(i - 1) : NULL;
178
179 bool isFall = entry->getSource()->equals(DamageSource::fall);
180 bool isOutOfWorld = entry->getSource()->equals(DamageSource::outOfWorld);
181
182 if ((isFall || isOutOfWorld) && (entry->getFallDistance() > 0) && (result == NULL || entry->getFallDistance() > bestFall))
183 {
184 if (i > 0)
185 {
186 result = previous;
187 }
188 else
189 {
190 result = entry;
191 }
192 bestFall = entry->getFallDistance();
193 }
194
195 if (entry->getLocation() != eLocation_GENERIC && (alternative == NULL || entry->getDamage() > altDamage))
196 {
197 alternative = entry;
198 }
199 }
200
201 if (bestFall > 5 && result != NULL)
202 {
203 return result;
204 }
205 else if (altDamage > 5 && alternative != NULL)
206 {
207 return alternative;
208 }
209 else
210 {
211 return NULL;
212 }
213}
214
215CombatTracker::eLOCATION CombatTracker::getFallLocation(CombatEntry *entry)
216{
217 return entry->getLocation();
218
219}
220
221bool CombatTracker::isTakingDamage()
222{
223 recheckStatus();
224 return takingDamage;
225}
226
227bool CombatTracker::isInCombat()
228{
229 recheckStatus();
230 return inCombat;
231}
232
233void CombatTracker::resetPreparedStatus()
234{
235 nextLocation = eLocation_GENERIC;
236}
237
238void CombatTracker::recheckStatus()
239{
240 int reset = inCombat ? RESET_COMBAT_STATUS_TIME : RESET_DAMAGE_STATUS_TIME;
241
242 if (takingDamage && mob->tickCount - lastDamageTime > reset)
243 {
244 for (AUTO_VAR(it,entries.begin()); it != entries.end(); ++it)
245 {
246 delete (*it);
247 }
248 entries.clear();
249 takingDamage = false;
250 inCombat = false;
251 }
252}