mirror of
				https://github.com/AxioDL/metaforce.git
				synced 2025-10-27 15:30:23 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			209 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "Runtime/World/CDamageVulnerability.hpp"
 | |
| 
 | |
| namespace metaforce {
 | |
| 
 | |
| const CDamageVulnerability CDamageVulnerability::sNormalVulnerability(
 | |
|     EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
 | |
|     EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
 | |
|     EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
 | |
|     EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
 | |
|     EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
 | |
|     EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EDeflectType::None);
 | |
| 
 | |
| const CDamageVulnerability CDamageVulnerability::sImmuneVulnerability(
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::None);
 | |
| 
 | |
| const CDamageVulnerability CDamageVulnerability::sReflectVulnerability(
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
 | |
|     EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::One);
 | |
| 
 | |
| const CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability(
 | |
|     EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
 | |
|     EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
 | |
|     EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
 | |
|     EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
 | |
|     EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
 | |
|     EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EDeflectType::None);
 | |
| 
 | |
| static constexpr bool is_deflect_direct(EVulnerability vuln) {
 | |
|   return vuln == EVulnerability::Deflect ||
 | |
|          (EVulnerability(u32(vuln) - u32(EVulnerability::DirectWeak)) < EVulnerability::Deflect) ||
 | |
|          vuln == EVulnerability::DirectImmune;
 | |
| }
 | |
| 
 | |
| static constexpr bool is_normal_or_weak(EVulnerability vuln) {
 | |
|   return vuln == EVulnerability::Weak || vuln == EVulnerability::Normal;
 | |
| }
 | |
| static constexpr bool is_not_deflect(EVulnerability vuln) { return vuln != EVulnerability::Deflect; }
 | |
| 
 | |
| void CDamageVulnerability::ConstructNew(CInputStream& in, int propCount) {
 | |
|   propCount -= 3;
 | |
| 
 | |
|   for (int i = 0; i < std::min(propCount, 15); ++i) {
 | |
|     x0_normal[i] = EVulnerability(in.ReadLong());
 | |
|   }
 | |
| 
 | |
|   if (propCount < 15) {
 | |
|     for (int i = propCount; i < 15; ++i) {
 | |
|       x0_normal[i] = EVulnerability::Deflect;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   for (int i = 15; i < propCount; ++i) {
 | |
|     in.ReadLong();
 | |
|   }
 | |
| 
 | |
|   x5c_deflected = EDeflectType(in.ReadLong());
 | |
|   in.ReadLong();
 | |
|   for (int i = 0; i < 4; ++i) {
 | |
|     x3c_charged[i] = EVulnerability(in.ReadLong());
 | |
|   }
 | |
| 
 | |
|   x60_chargedDeflected = EDeflectType(in.ReadLong());
 | |
|   in.ReadLong();
 | |
|   for (int i = 0; i < 4; ++i) {
 | |
|     x4c_combo[i] = EVulnerability(in.ReadLong());
 | |
|   }
 | |
| 
 | |
|   x64_comboDeflected = EDeflectType(in.ReadLong());
 | |
| }
 | |
| 
 | |
| CDamageVulnerability::CDamageVulnerability(CInputStream& in) {
 | |
|   u32 propCount = in.ReadLong();
 | |
|   if (propCount == 11) {
 | |
|     for (int i = 0; i < 15; ++i) {
 | |
|       x0_normal[i] = EVulnerability(in.ReadLong());
 | |
|     }
 | |
| 
 | |
|     x5c_deflected = EDeflectType(in.ReadLong());
 | |
|     x3c_charged[0] = x0_normal[0];
 | |
|     x4c_combo[0] = x0_normal[0];
 | |
|     x3c_charged[1] = x0_normal[1];
 | |
|     x4c_combo[1] = x0_normal[1];
 | |
|     x3c_charged[2] = x0_normal[2];
 | |
|     x4c_combo[2] = x0_normal[2];
 | |
|     x3c_charged[3] = x0_normal[3];
 | |
|     x4c_combo[3] = x0_normal[3];
 | |
|   } else {
 | |
|     ConstructNew(in, propCount);
 | |
|   }
 | |
| }
 | |
| 
 | |
| EDeflectType CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const {
 | |
|   if (mode.IsCharged()) {
 | |
|     return x60_chargedDeflected;
 | |
|   }
 | |
|   if (mode.IsComboed()) {
 | |
|     return x64_comboDeflected;
 | |
|   }
 | |
|   return x5c_deflected;
 | |
| }
 | |
| 
 | |
| static inline bool check_hurts(EVulnerability vuln, bool direct) {
 | |
|   return direct == 0
 | |
|              ? (is_normal_or_weak(vuln) || vuln == EVulnerability::DirectWeak || vuln == EVulnerability::DirectNormal)
 | |
|              : is_normal_or_weak(vuln);
 | |
| }
 | |
| 
 | |
| bool CDamageVulnerability::WeaponHurts(const CWeaponMode& mode, bool ignoreDirect) const {
 | |
|   if (mode.GetType() < EWeaponType::Power || mode.GetType() > EWeaponType::OrangePhazon) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   if (mode.IsInstantKill()) {
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   bool normalHurts = check_hurts(x0_normal[u32(mode.GetType())], ignoreDirect);
 | |
|   bool chargedHurts =
 | |
|       (mode.GetType() < EWeaponType::Bomb) ? check_hurts(x3c_charged[u32(mode.GetType())], ignoreDirect) : true;
 | |
|   bool comboedHurts =
 | |
|       (mode.GetType() < EWeaponType::Bomb) ? check_hurts(x4c_combo[u32(mode.GetType())], ignoreDirect) : true;
 | |
| 
 | |
|   return (normalHurts && !mode.IsCharged() && !mode.IsComboed()) || (chargedHurts && mode.IsCharged()) ||
 | |
|          (comboedHurts && mode.IsComboed());
 | |
| }
 | |
| 
 | |
| static inline bool check_hits(EVulnerability vuln, bool direct) {
 | |
|   if (!direct) {
 | |
|     return is_not_deflect(vuln);
 | |
|   }
 | |
|   if (vuln == EVulnerability::Deflect ||
 | |
|       (static_cast<EVulnerability>(static_cast<u32>(vuln) - static_cast<u32>(EVulnerability::DirectWeak)) <=
 | |
|        EVulnerability::Normal) ||
 | |
|       vuln == EVulnerability::DirectImmune) {
 | |
|     return false;
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect) const {
 | |
|   if (mode.GetType() < EWeaponType::Power || mode.GetType() > EWeaponType::OrangePhazon) {
 | |
|     return false;
 | |
|   }
 | |
|   if (mode.IsInstantKill()) {
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   bool normalHits = check_hits(x0_normal[u32(mode.GetType())], checkDirect);
 | |
|   bool chargedHits =
 | |
|       mode.GetType() < EWeaponType::Bomb ? check_hits(x3c_charged[u32(mode.GetType())], checkDirect) : true;
 | |
|   bool comboedHits =
 | |
|       mode.GetType() < EWeaponType::Bomb ? check_hits(x4c_combo[u32(mode.GetType())], checkDirect) : true;
 | |
|   bool result = false;
 | |
|   if ((normalHits && !mode.IsCharged() && !mode.IsComboed()) || (chargedHits && mode.IsCharged()) ||
 | |
|       (comboedHits && mode.IsComboed())) {
 | |
|     result = true;
 | |
|   }
 | |
| 
 | |
|   return (normalHits && !mode.IsCharged() && !mode.IsComboed()) || (chargedHits && mode.IsCharged()) ||
 | |
|          (comboedHits && mode.IsComboed());
 | |
| }
 | |
| 
 | |
| inline EVulnerability direct_to_normal(EVulnerability vuln) {
 | |
|   if (vuln == EVulnerability::DirectWeak) {
 | |
|     return EVulnerability::Weak;
 | |
|   }
 | |
|   if (vuln == EVulnerability::DirectNormal) {
 | |
|     return EVulnerability::Normal;
 | |
|   }
 | |
|   if (vuln == EVulnerability::DirectImmune) {
 | |
|     return EVulnerability::Immune;
 | |
|   }
 | |
|   return vuln;
 | |
| }
 | |
| 
 | |
| EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const {
 | |
|   if (mode.GetType() < EWeaponType::Power || mode.GetType() > EWeaponType::OrangePhazon) {
 | |
|     return EVulnerability::Deflect;
 | |
|   }
 | |
| 
 | |
|   if (mode.IsInstantKill()) {
 | |
|     return EVulnerability::Normal;
 | |
|   }
 | |
| 
 | |
|   EVulnerability vuln = x0_normal[u32(mode.GetType())];
 | |
|   EWeaponType type = mode.GetType();
 | |
|   if (mode.IsCharged()) {
 | |
|     vuln = type < EWeaponType::Bomb ? x3c_charged[u32(type)] : EVulnerability::Normal;
 | |
|   }
 | |
| 
 | |
|   if (mode.IsComboed()) {
 | |
|     vuln = type < EWeaponType::Bomb ? x4c_combo[u32(type)] : EVulnerability::Normal;
 | |
|   }
 | |
|   if (ignoreDirect == 1) {
 | |
|     return vuln;
 | |
|   }
 | |
|   return direct_to_normal(vuln);
 | |
| }
 | |
| } // namespace metaforce
 |