the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 252 lines 7.0 kB view raw
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}