mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 22:26:41 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			619 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			619 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "loadmgef.hpp"
 | |
| 
 | |
| #include <sstream>
 | |
| 
 | |
| #include "esmreader.hpp"
 | |
| #include "esmwriter.hpp"
 | |
| 
 | |
| #include <components/misc/strings/algorithm.hpp>
 | |
| 
 | |
| namespace ESM
 | |
| {
 | |
|     namespace
 | |
|     {
 | |
|         static const char* sIds[MagicEffect::Length] = {
 | |
|             "WaterBreathing",
 | |
|             "SwiftSwim",
 | |
|             "WaterWalking",
 | |
|             "Shield",
 | |
|             "FireShield",
 | |
|             "LightningShield",
 | |
|             "FrostShield",
 | |
|             "Burden",
 | |
|             "Feather",
 | |
|             "Jump",
 | |
|             "Levitate",
 | |
|             "SlowFall",
 | |
|             "Lock",
 | |
|             "Open",
 | |
|             "FireDamage",
 | |
|             "ShockDamage",
 | |
|             "FrostDamage",
 | |
|             "DrainAttribute",
 | |
|             "DrainHealth",
 | |
|             "DrainMagicka",
 | |
|             "DrainFatigue",
 | |
|             "DrainSkill",
 | |
|             "DamageAttribute",
 | |
|             "DamageHealth",
 | |
|             "DamageMagicka",
 | |
|             "DamageFatigue",
 | |
|             "DamageSkill",
 | |
|             "Poison",
 | |
|             "WeaknessToFire",
 | |
|             "WeaknessToFrost",
 | |
|             "WeaknessToShock",
 | |
|             "WeaknessToMagicka",
 | |
|             "WeaknessToCommonDisease",
 | |
|             "WeaknessToBlightDisease",
 | |
|             "WeaknessToCorprusDisease",
 | |
|             "WeaknessToPoison",
 | |
|             "WeaknessToNormalWeapons",
 | |
|             "DisintegrateWeapon",
 | |
|             "DisintegrateArmor",
 | |
|             "Invisibility",
 | |
|             "Chameleon",
 | |
|             "Light",
 | |
|             "Sanctuary",
 | |
|             "NightEye",
 | |
|             "Charm",
 | |
|             "Paralyze",
 | |
|             "Silence",
 | |
|             "Blind",
 | |
|             "Sound",
 | |
|             "CalmHumanoid",
 | |
|             "CalmCreature",
 | |
|             "FrenzyHumanoid",
 | |
|             "FrenzyCreature",
 | |
|             "DemoralizeHumanoid",
 | |
|             "DemoralizeCreature",
 | |
|             "RallyHumanoid",
 | |
|             "RallyCreature",
 | |
|             "Dispel",
 | |
|             "Soultrap",
 | |
|             "Telekinesis",
 | |
|             "Mark",
 | |
|             "Recall",
 | |
|             "DivineIntervention",
 | |
|             "AlmsiviIntervention",
 | |
|             "DetectAnimal",
 | |
|             "DetectEnchantment",
 | |
|             "DetectKey",
 | |
|             "SpellAbsorption",
 | |
|             "Reflect",
 | |
|             "CureCommonDisease",
 | |
|             "CureBlightDisease",
 | |
|             "CureCorprusDisease",
 | |
|             "CurePoison",
 | |
|             "CureParalyzation",
 | |
|             "RestoreAttribute",
 | |
|             "RestoreHealth",
 | |
|             "RestoreMagicka",
 | |
|             "RestoreFatigue",
 | |
|             "RestoreSkill",
 | |
|             "FortifyAttribute",
 | |
|             "FortifyHealth",
 | |
|             "FortifyMagicka",
 | |
|             "FortifyFatigue",
 | |
|             "FortifySkill",
 | |
|             "FortifyMaximumMagicka",
 | |
|             "AbsorbAttribute",
 | |
|             "AbsorbHealth",
 | |
|             "AbsorbMagicka",
 | |
|             "AbsorbFatigue",
 | |
|             "AbsorbSkill",
 | |
|             "ResistFire",
 | |
|             "ResistFrost",
 | |
|             "ResistShock",
 | |
|             "ResistMagicka",
 | |
|             "ResistCommonDisease",
 | |
|             "ResistBlightDisease",
 | |
|             "ResistCorprusDisease",
 | |
|             "ResistPoison",
 | |
|             "ResistNormalWeapons",
 | |
|             "ResistParalysis",
 | |
|             "RemoveCurse",
 | |
|             "TurnUndead",
 | |
|             "SummonScamp",
 | |
|             "SummonClannfear",
 | |
|             "SummonDaedroth",
 | |
|             "SummonDremora",
 | |
|             "SummonAncestralGhost",
 | |
|             "SummonSkeletalMinion",
 | |
|             "SummonBonewalker",
 | |
|             "SummonGreaterBonewalker",
 | |
|             "SummonBonelord",
 | |
|             "SummonWingedTwilight",
 | |
|             "SummonHunger",
 | |
|             "SummonGoldenSaint",
 | |
|             "SummonFlameAtronach",
 | |
|             "SummonFrostAtronach",
 | |
|             "SummonStormAtronach",
 | |
|             "FortifyAttack",
 | |
|             "CommandCreature",
 | |
|             "CommandHumanoid",
 | |
|             "BoundDagger",
 | |
|             "BoundLongsword",
 | |
|             "BoundMace",
 | |
|             "BoundBattleAxe",
 | |
|             "BoundSpear",
 | |
|             "BoundLongbow",
 | |
|             "ExtraSpell",
 | |
|             "BoundCuirass",
 | |
|             "BoundHelm",
 | |
|             "BoundBoots",
 | |
|             "BoundShield",
 | |
|             "BoundGloves",
 | |
|             "Corprus",
 | |
|             "Vampirism",
 | |
|             "SummonCenturionSphere",
 | |
|             "SunDamage",
 | |
|             "StuntedMagicka",
 | |
| 
 | |
|             // Tribunal only
 | |
|             "SummonFabricant",
 | |
| 
 | |
|             // Bloodmoon only
 | |
|             "SummonWolf",
 | |
|             "SummonBear",
 | |
|             "SummonBonewolf",
 | |
|             "SummonCreature04",
 | |
|             "SummonCreature05",
 | |
|         };
 | |
| 
 | |
|         const int NumberOfHardcodedFlags = 143;
 | |
|         const int HardcodedFlags[NumberOfHardcodedFlags] = { 0x11c8, 0x11c0, 0x11c8, 0x11e0, 0x11e0, 0x11e0, 0x11e0,
 | |
|             0x11d0, 0x11c0, 0x11c0, 0x11e0, 0x11c0, 0x11184, 0x11184, 0x1f0, 0x1f0, 0x1f0, 0x11d2, 0x11f0, 0x11d0,
 | |
|             0x11d0, 0x11d1, 0x1d2, 0x1f0, 0x1d0, 0x1d0, 0x1d1, 0x1f0, 0x11d0, 0x11d0, 0x11d0, 0x11d0, 0x11d0, 0x11d0,
 | |
|             0x11d0, 0x11d0, 0x11d0, 0x1d0, 0x1d0, 0x11c8, 0x31c0, 0x11c0, 0x11c0, 0x11c0, 0x1180, 0x11d8, 0x11d8,
 | |
|             0x11d0, 0x11d0, 0x11180, 0x11180, 0x11180, 0x11180, 0x11180, 0x11180, 0x11180, 0x11180, 0x11c4, 0x111b8,
 | |
|             0x1040, 0x104c, 0x104c, 0x104c, 0x104c, 0x1040, 0x1040, 0x1040, 0x11c0, 0x11c0, 0x1cc, 0x1cc, 0x1cc, 0x1cc,
 | |
|             0x1cc, 0x1c2, 0x1c0, 0x1c0, 0x1c0, 0x1c1, 0x11c2, 0x11c0, 0x11c0, 0x11c0, 0x11c1, 0x11c0, 0x21192, 0x20190,
 | |
|             0x20190, 0x20190, 0x21191, 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c0,
 | |
|             0x1c0, 0x11190, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048, 0x9048,
 | |
|             0x9048, 0x9048, 0x9048, 0x9048, 0x11c0, 0x1180, 0x1180, 0x5048, 0x5048, 0x5048, 0x5048, 0x5048, 0x5048,
 | |
|             0x1188, 0x5048, 0x5048, 0x5048, 0x5048, 0x5048, 0x1048, 0x104c, 0x1048, 0x40, 0x11c8, 0x1048, 0x1048,
 | |
|             0x1048, 0x1048, 0x1048, 0x1048 };
 | |
|     }
 | |
| }
 | |
| 
 | |
| namespace ESM
 | |
| {
 | |
|     void MagicEffect::load(ESMReader& esm, bool& isDeleted)
 | |
|     {
 | |
|         isDeleted = false; // MagicEffect record can't be deleted now (may be changed in the future)
 | |
|         mRecordFlags = esm.getRecordFlags();
 | |
| 
 | |
|         esm.getHNT(mIndex, "INDX");
 | |
| 
 | |
|         mId = ESM::RefId::stringRefId(indexToId(mIndex));
 | |
| 
 | |
|         esm.getHNTSized<36>(mData, "MEDT");
 | |
|         if (esm.getFormat() == 0)
 | |
|         {
 | |
|             // don't allow mods to change fixed flags in the legacy format
 | |
|             mData.mFlags &= (AllowSpellmaking | AllowEnchanting | NegativeLight);
 | |
|             if (mIndex >= 0 && mIndex < NumberOfHardcodedFlags)
 | |
|                 mData.mFlags |= HardcodedFlags[mIndex];
 | |
|         }
 | |
| 
 | |
|         // vanilla MW accepts the _SND subrecords before or after DESC... I hope
 | |
|         // this isn't true for other records, or we have to do a mass-refactor
 | |
|         while (esm.hasMoreSubs())
 | |
|         {
 | |
|             esm.getSubName();
 | |
|             switch (esm.retSubName().toInt())
 | |
|             {
 | |
|                 case fourCC("ITEX"):
 | |
|                     mIcon = esm.getHString();
 | |
|                     break;
 | |
|                 case fourCC("PTEX"):
 | |
|                     mParticle = esm.getHString();
 | |
|                     break;
 | |
|                 case fourCC("BSND"):
 | |
|                     mBoltSound = esm.getRefId();
 | |
|                     break;
 | |
|                 case fourCC("CSND"):
 | |
|                     mCastSound = esm.getRefId();
 | |
|                     break;
 | |
|                 case fourCC("HSND"):
 | |
|                     mHitSound = esm.getRefId();
 | |
|                     break;
 | |
|                 case fourCC("ASND"):
 | |
|                     mAreaSound = esm.getRefId();
 | |
|                     break;
 | |
|                 case fourCC("CVFX"):
 | |
|                     mCasting = esm.getRefId();
 | |
|                     break;
 | |
|                 case fourCC("BVFX"):
 | |
|                     mBolt = esm.getRefId();
 | |
|                     break;
 | |
|                 case fourCC("HVFX"):
 | |
|                     mHit = esm.getRefId();
 | |
|                     break;
 | |
|                 case fourCC("AVFX"):
 | |
|                     mArea = esm.getRefId();
 | |
|                     break;
 | |
|                 case fourCC("DESC"):
 | |
|                     mDescription = esm.getHString();
 | |
|                     break;
 | |
|                 default:
 | |
|                     esm.fail("Unknown subrecord");
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     void MagicEffect::save(ESMWriter& esm, bool /*isDeleted*/) const
 | |
|     {
 | |
|         esm.writeHNT("INDX", mIndex);
 | |
| 
 | |
|         esm.writeHNT("MEDT", mData, 36);
 | |
| 
 | |
|         esm.writeHNOCString("ITEX", mIcon);
 | |
|         esm.writeHNOCString("PTEX", mParticle);
 | |
|         esm.writeHNOCString("BSND", mBoltSound.getRefIdString());
 | |
|         esm.writeHNOCString("CSND", mCastSound.getRefIdString());
 | |
|         esm.writeHNOCString("HSND", mHitSound.getRefIdString());
 | |
|         esm.writeHNOCString("ASND", mAreaSound.getRefIdString());
 | |
| 
 | |
|         esm.writeHNOCString("CVFX", mCasting.getRefIdString());
 | |
|         esm.writeHNOCString("BVFX", mBolt.getRefIdString());
 | |
|         esm.writeHNOCString("HVFX", mHit.getRefIdString());
 | |
|         esm.writeHNOCString("AVFX", mArea.getRefIdString());
 | |
| 
 | |
|         esm.writeHNOString("DESC", mDescription);
 | |
|     }
 | |
| 
 | |
|     short MagicEffect::getResistanceEffect(short effect)
 | |
|     {
 | |
|         // Source https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attribute
 | |
| 
 | |
|         // <Effect, Effect providing resistance against first effect>
 | |
|         static std::map<short, short> effects;
 | |
|         if (effects.empty())
 | |
|         {
 | |
|             effects[DisintegrateArmor] = Sanctuary;
 | |
|             effects[DisintegrateWeapon] = Sanctuary;
 | |
| 
 | |
|             for (int i = DrainAttribute; i <= DamageSkill; ++i)
 | |
|                 effects[i] = ResistMagicka;
 | |
|             for (int i = AbsorbAttribute; i <= AbsorbSkill; ++i)
 | |
|                 effects[i] = ResistMagicka;
 | |
|             for (int i = WeaknessToFire; i <= WeaknessToNormalWeapons; ++i)
 | |
|                 effects[i] = ResistMagicka;
 | |
| 
 | |
|             effects[Burden] = ResistMagicka;
 | |
|             effects[Charm] = ResistMagicka;
 | |
|             effects[Silence] = ResistMagicka;
 | |
|             effects[Blind] = ResistMagicka;
 | |
|             effects[Sound] = ResistMagicka;
 | |
| 
 | |
|             for (int i = 0; i < 2; ++i)
 | |
|             {
 | |
|                 effects[CalmHumanoid + i] = ResistMagicka;
 | |
|                 effects[FrenzyHumanoid + i] = ResistMagicka;
 | |
|                 effects[DemoralizeHumanoid + i] = ResistMagicka;
 | |
|                 effects[RallyHumanoid + i] = ResistMagicka;
 | |
|             }
 | |
| 
 | |
|             effects[TurnUndead] = ResistMagicka;
 | |
| 
 | |
|             effects[FireDamage] = ResistFire;
 | |
|             effects[FrostDamage] = ResistFrost;
 | |
|             effects[ShockDamage] = ResistShock;
 | |
|             effects[Vampirism] = ResistCommonDisease;
 | |
|             effects[Corprus] = ResistCorprusDisease;
 | |
|             effects[Poison] = ResistPoison;
 | |
|             effects[Paralyze] = ResistParalysis;
 | |
|         }
 | |
| 
 | |
|         if (effects.find(effect) != effects.end())
 | |
|             return effects[effect];
 | |
|         else
 | |
|             return -1;
 | |
|     }
 | |
| 
 | |
|     short MagicEffect::getWeaknessEffect(short effect)
 | |
|     {
 | |
|         static std::map<short, short> effects;
 | |
|         if (effects.empty())
 | |
|         {
 | |
|             for (int i = DrainAttribute; i <= DamageSkill; ++i)
 | |
|                 effects[i] = WeaknessToMagicka;
 | |
|             for (int i = AbsorbAttribute; i <= AbsorbSkill; ++i)
 | |
|                 effects[i] = WeaknessToMagicka;
 | |
|             for (int i = WeaknessToFire; i <= WeaknessToNormalWeapons; ++i)
 | |
|                 effects[i] = WeaknessToMagicka;
 | |
| 
 | |
|             effects[Burden] = WeaknessToMagicka;
 | |
|             effects[Charm] = WeaknessToMagicka;
 | |
|             effects[Silence] = WeaknessToMagicka;
 | |
|             effects[Blind] = WeaknessToMagicka;
 | |
|             effects[Sound] = WeaknessToMagicka;
 | |
| 
 | |
|             for (int i = 0; i < 2; ++i)
 | |
|             {
 | |
|                 effects[CalmHumanoid + i] = WeaknessToMagicka;
 | |
|                 effects[FrenzyHumanoid + i] = WeaknessToMagicka;
 | |
|                 effects[DemoralizeHumanoid + i] = WeaknessToMagicka;
 | |
|                 effects[RallyHumanoid + i] = WeaknessToMagicka;
 | |
|             }
 | |
| 
 | |
|             effects[TurnUndead] = WeaknessToMagicka;
 | |
| 
 | |
|             effects[FireDamage] = WeaknessToFire;
 | |
|             effects[FrostDamage] = WeaknessToFrost;
 | |
|             effects[ShockDamage] = WeaknessToShock;
 | |
|             effects[Vampirism] = WeaknessToCommonDisease;
 | |
|             effects[Corprus] = WeaknessToCorprusDisease;
 | |
|             effects[Poison] = WeaknessToPoison;
 | |
| 
 | |
|             effects[Paralyze] = -1;
 | |
|         }
 | |
| 
 | |
|         if (effects.find(effect) != effects.end())
 | |
|             return effects[effect];
 | |
|         else
 | |
|             return -1;
 | |
|     }
 | |
| 
 | |
|     static std::map<short, std::string> genNameMap()
 | |
|     {
 | |
|         // Map effect ID to GMST name
 | |
|         // http://www.uesp.net/morrow/hints/mweffects.shtml
 | |
|         std::map<short, std::string> names;
 | |
|         names[85] = "sEffectAbsorbAttribute";
 | |
|         names[88] = "sEffectAbsorbFatigue";
 | |
|         names[86] = "sEffectAbsorbHealth";
 | |
|         names[87] = "sEffectAbsorbSpellPoints";
 | |
|         names[89] = "sEffectAbsorbSkill";
 | |
|         names[63] = "sEffectAlmsiviIntervention";
 | |
|         names[47] = "sEffectBlind";
 | |
|         names[123] = "sEffectBoundBattleAxe";
 | |
|         names[129] = "sEffectBoundBoots";
 | |
|         names[127] = "sEffectBoundCuirass";
 | |
|         names[120] = "sEffectBoundDagger";
 | |
|         names[131] = "sEffectBoundGloves";
 | |
|         names[128] = "sEffectBoundHelm";
 | |
|         names[125] = "sEffectBoundLongbow";
 | |
|         names[126] = "sEffectExtraSpell";
 | |
|         names[121] = "sEffectBoundLongsword";
 | |
|         names[122] = "sEffectBoundMace";
 | |
|         names[130] = "sEffectBoundShield";
 | |
|         names[124] = "sEffectBoundSpear";
 | |
|         names[7] = "sEffectBurden";
 | |
|         names[50] = "sEffectCalmCreature";
 | |
|         names[49] = "sEffectCalmHumanoid";
 | |
|         names[40] = "sEffectChameleon";
 | |
|         names[44] = "sEffectCharm";
 | |
|         names[118] = "sEffectCommandCreatures";
 | |
|         names[119] = "sEffectCommandHumanoids";
 | |
|         names[132] = "sEffectCorpus"; // NB this typo. (bethesda made it)
 | |
|         names[70] = "sEffectCureBlightDisease";
 | |
|         names[69] = "sEffectCureCommonDisease";
 | |
|         names[71] = "sEffectCureCorprusDisease";
 | |
|         names[73] = "sEffectCureParalyzation";
 | |
|         names[72] = "sEffectCurePoison";
 | |
|         names[22] = "sEffectDamageAttribute";
 | |
|         names[25] = "sEffectDamageFatigue";
 | |
|         names[23] = "sEffectDamageHealth";
 | |
|         names[24] = "sEffectDamageMagicka";
 | |
|         names[26] = "sEffectDamageSkill";
 | |
|         names[54] = "sEffectDemoralizeCreature";
 | |
|         names[53] = "sEffectDemoralizeHumanoid";
 | |
|         names[64] = "sEffectDetectAnimal";
 | |
|         names[65] = "sEffectDetectEnchantment";
 | |
|         names[66] = "sEffectDetectKey";
 | |
|         names[38] = "sEffectDisintegrateArmor";
 | |
|         names[37] = "sEffectDisintegrateWeapon";
 | |
|         names[57] = "sEffectDispel";
 | |
|         names[62] = "sEffectDivineIntervention";
 | |
|         names[17] = "sEffectDrainAttribute";
 | |
|         names[20] = "sEffectDrainFatigue";
 | |
|         names[18] = "sEffectDrainHealth";
 | |
|         names[19] = "sEffectDrainSpellpoints";
 | |
|         names[21] = "sEffectDrainSkill";
 | |
|         names[8] = "sEffectFeather";
 | |
|         names[14] = "sEffectFireDamage";
 | |
|         names[4] = "sEffectFireShield";
 | |
|         names[117] = "sEffectFortifyAttackBonus";
 | |
|         names[79] = "sEffectFortifyAttribute";
 | |
|         names[82] = "sEffectFortifyFatigue";
 | |
|         names[80] = "sEffectFortifyHealth";
 | |
|         names[81] = "sEffectFortifySpellpoints";
 | |
|         names[84] = "sEffectFortifyMagickaMultiplier";
 | |
|         names[83] = "sEffectFortifySkill";
 | |
|         names[52] = "sEffectFrenzyCreature";
 | |
|         names[51] = "sEffectFrenzyHumanoid";
 | |
|         names[16] = "sEffectFrostDamage";
 | |
|         names[6] = "sEffectFrostShield";
 | |
|         names[39] = "sEffectInvisibility";
 | |
|         names[9] = "sEffectJump";
 | |
|         names[10] = "sEffectLevitate";
 | |
|         names[41] = "sEffectLight";
 | |
|         names[5] = "sEffectLightningShield";
 | |
|         names[12] = "sEffectLock";
 | |
|         names[60] = "sEffectMark";
 | |
|         names[43] = "sEffectNightEye";
 | |
|         names[13] = "sEffectOpen";
 | |
|         names[45] = "sEffectParalyze";
 | |
|         names[27] = "sEffectPoison";
 | |
|         names[56] = "sEffectRallyCreature";
 | |
|         names[55] = "sEffectRallyHumanoid";
 | |
|         names[61] = "sEffectRecall";
 | |
|         names[68] = "sEffectReflect";
 | |
|         names[100] = "sEffectRemoveCurse";
 | |
|         names[95] = "sEffectResistBlightDisease";
 | |
|         names[94] = "sEffectResistCommonDisease";
 | |
|         names[96] = "sEffectResistCorprusDisease";
 | |
|         names[90] = "sEffectResistFire";
 | |
|         names[91] = "sEffectResistFrost";
 | |
|         names[93] = "sEffectResistMagicka";
 | |
|         names[98] = "sEffectResistNormalWeapons";
 | |
|         names[99] = "sEffectResistParalysis";
 | |
|         names[97] = "sEffectResistPoison";
 | |
|         names[92] = "sEffectResistShock";
 | |
|         names[74] = "sEffectRestoreAttribute";
 | |
|         names[77] = "sEffectRestoreFatigue";
 | |
|         names[75] = "sEffectRestoreHealth";
 | |
|         names[76] = "sEffectRestoreSpellPoints";
 | |
|         names[78] = "sEffectRestoreSkill";
 | |
|         names[42] = "sEffectSanctuary";
 | |
|         names[3] = "sEffectShield";
 | |
|         names[15] = "sEffectShockDamage";
 | |
|         names[46] = "sEffectSilence";
 | |
|         names[11] = "sEffectSlowFall";
 | |
|         names[58] = "sEffectSoultrap";
 | |
|         names[48] = "sEffectSound";
 | |
|         names[67] = "sEffectSpellAbsorption";
 | |
|         names[136] = "sEffectStuntedMagicka";
 | |
|         names[106] = "sEffectSummonAncestralGhost";
 | |
|         names[110] = "sEffectSummonBonelord";
 | |
|         names[108] = "sEffectSummonLeastBonewalker";
 | |
|         names[134] = "sEffectSummonCenturionSphere";
 | |
|         names[103] = "sEffectSummonClannfear";
 | |
|         names[104] = "sEffectSummonDaedroth";
 | |
|         names[105] = "sEffectSummonDremora";
 | |
|         names[114] = "sEffectSummonFlameAtronach";
 | |
|         names[115] = "sEffectSummonFrostAtronach";
 | |
|         names[113] = "sEffectSummonGoldenSaint";
 | |
|         names[109] = "sEffectSummonGreaterBonewalker";
 | |
|         names[112] = "sEffectSummonHunger";
 | |
|         names[102] = "sEffectSummonScamp";
 | |
|         names[107] = "sEffectSummonSkeletalMinion";
 | |
|         names[116] = "sEffectSummonStormAtronach";
 | |
|         names[111] = "sEffectSummonWingedTwilight";
 | |
|         names[135] = "sEffectSunDamage";
 | |
|         names[1] = "sEffectSwiftSwim";
 | |
|         names[59] = "sEffectTelekinesis";
 | |
|         names[101] = "sEffectTurnUndead";
 | |
|         names[133] = "sEffectVampirism";
 | |
|         names[0] = "sEffectWaterBreathing";
 | |
|         names[2] = "sEffectWaterWalking";
 | |
|         names[33] = "sEffectWeaknesstoBlightDisease";
 | |
|         names[32] = "sEffectWeaknesstoCommonDisease";
 | |
|         names[34] = "sEffectWeaknesstoCorprusDisease";
 | |
|         names[28] = "sEffectWeaknesstoFire";
 | |
|         names[29] = "sEffectWeaknesstoFrost";
 | |
|         names[31] = "sEffectWeaknesstoMagicka";
 | |
|         names[36] = "sEffectWeaknesstoNormalWeapons";
 | |
|         names[35] = "sEffectWeaknesstoPoison";
 | |
|         names[30] = "sEffectWeaknesstoShock";
 | |
| 
 | |
|         // bloodmoon
 | |
|         names[138] = "sEffectSummonCreature01";
 | |
|         names[139] = "sEffectSummonCreature02";
 | |
|         names[140] = "sEffectSummonCreature03";
 | |
|         names[141] = "sEffectSummonCreature04";
 | |
|         names[142] = "sEffectSummonCreature05";
 | |
| 
 | |
|         // tribunal
 | |
|         names[137] = "sEffectSummonFabricant";
 | |
| 
 | |
|         return names;
 | |
|     }
 | |
|     const std::map<short, std::string> MagicEffect::sNames = genNameMap();
 | |
| 
 | |
|     const std::string& MagicEffect::effectIdToString(short effectID)
 | |
|     {
 | |
|         std::map<short, std::string>::const_iterator name = sNames.find(effectID);
 | |
|         if (name == sNames.end())
 | |
|             throw std::runtime_error(std::string("Unimplemented effect ID ") + std::to_string(effectID));
 | |
| 
 | |
|         return name->second;
 | |
|     }
 | |
| 
 | |
|     class FindSecond
 | |
|     {
 | |
|         std::string_view mName;
 | |
| 
 | |
|     public:
 | |
|         FindSecond(std::string_view name)
 | |
|             : mName(name)
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         bool operator()(const std::pair<short, std::string>& item) const
 | |
|         {
 | |
|             if (Misc::StringUtils::ciEqual(item.second, mName))
 | |
|                 return true;
 | |
|             return false;
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     short MagicEffect::effectStringToId(std::string_view effect)
 | |
|     {
 | |
|         std::map<short, std::string>::const_iterator name;
 | |
| 
 | |
|         name = std::find_if(sNames.begin(), sNames.end(), FindSecond(effect));
 | |
|         if (name == sNames.end())
 | |
|             throw std::runtime_error("Unimplemented effect " + std::string(effect));
 | |
| 
 | |
|         return name->first;
 | |
|     }
 | |
| 
 | |
|     MagicEffect::MagnitudeDisplayType MagicEffect::getMagnitudeDisplayType() const
 | |
|     {
 | |
|         if (mData.mFlags & NoMagnitude)
 | |
|             return MDT_None;
 | |
|         if (mIndex == 84)
 | |
|             return MDT_TimesInt;
 | |
|         if (mIndex == 59 || (mIndex >= 64 && mIndex <= 66))
 | |
|             return MDT_Feet;
 | |
|         if (mIndex == 118 || mIndex == 119)
 | |
|             return MDT_Level;
 | |
|         if ((mIndex >= 28 && mIndex <= 36) || (mIndex >= 90 && mIndex <= 99) || mIndex == 40 || mIndex == 47
 | |
|             || mIndex == 57 || mIndex == 68)
 | |
|             return MDT_Percentage;
 | |
| 
 | |
|         return MDT_Points;
 | |
|     }
 | |
| 
 | |
|     void MagicEffect::blank()
 | |
|     {
 | |
|         mRecordFlags = 0;
 | |
|         mData.mSchool = 0;
 | |
|         mData.mBaseCost = 0;
 | |
|         mData.mFlags = 0;
 | |
|         mData.mRed = 0;
 | |
|         mData.mGreen = 0;
 | |
|         mData.mBlue = 0;
 | |
|         mData.mSpeed = 0;
 | |
| 
 | |
|         mIcon.clear();
 | |
|         mParticle.clear();
 | |
|         mCasting = ESM::RefId::sEmpty;
 | |
|         mHit = ESM::RefId::sEmpty;
 | |
|         mArea = ESM::RefId::sEmpty;
 | |
|         mBolt = ESM::RefId::sEmpty;
 | |
|         mCastSound = ESM::RefId::sEmpty;
 | |
|         mBoltSound = ESM::RefId::sEmpty;
 | |
|         mHitSound = ESM::RefId::sEmpty;
 | |
|         mAreaSound = ESM::RefId::sEmpty;
 | |
|         mDescription.clear();
 | |
|     }
 | |
| 
 | |
|     std::string MagicEffect::indexToId(int index)
 | |
|     {
 | |
|         std::ostringstream stream;
 | |
| 
 | |
|         if (index != -1)
 | |
|         {
 | |
|             stream << "#";
 | |
| 
 | |
|             if (index < 100)
 | |
|             {
 | |
|                 stream << "0";
 | |
| 
 | |
|                 if (index < 10)
 | |
|                     stream << "0";
 | |
|             }
 | |
| 
 | |
|             stream << index;
 | |
| 
 | |
|             if (index >= 0 && index < Length)
 | |
|                 stream << sIds[index];
 | |
|         }
 | |
| 
 | |
|         return stream.str();
 | |
|     }
 | |
| }
 |