package d2records import ( "fmt" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2calculation/d2parser" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt" ) // LoadSkills loads skills.txt file contents into a skill record map //nolint:funlen // Makes no sense to split func skillDetailsLoader(r *RecordManager, d *d2txt.DataDictionary) error { records := make(map[int]*SkillRecord) parser := d2parser.New() for d.Next() { name := d.String("skill") parser.SetCurrentReference("skill", name) anim, err := animToEnum(d.String("anim")) if err != nil { return err } record := &SkillRecord{ Skill: d.String("skill"), ID: d.Number("Id"), Charclass: d.String("charclass"), Skilldesc: d.String("skilldesc"), Srvstfunc: d.Number("srvstfunc"), Srvdofunc: d.Number("srvdofunc"), Prgstack: d.Bool("prgstack"), Srvprgfunc1: d.Number("srvprgfunc1"), Srvprgfunc2: d.Number("srvprgfunc2"), Srvprgfunc3: d.Number("srvprgfunc3"), Prgcalc1: parser.Parse(d.String("prgcalc1")), Prgcalc2: parser.Parse(d.String("prgcalc2")), Prgcalc3: parser.Parse(d.String("prgcalc3")), Prgdam: d.Number("prgdam"), Srvmissile: d.String("srvmissile"), Decquant: d.Bool("decquant"), Lob: d.Bool("lob"), Srvmissilea: d.String("srvmissilea"), Srvmissileb: d.String("srvmissileb"), Srvmissilec: d.String("srvmissilec"), Srvoverlay: d.String("srvoverlay"), Aurafilter: d.Number("aurafilter"), Aurastate: d.String("aurastate"), Auratargetstate: d.String("auratargetstate"), Auralencalc: parser.Parse(d.String("auralencalc")), Aurarangecalc: parser.Parse(d.String("aurarangecalc")), Aurastat1: d.String("aurastat1"), Aurastatcalc1: parser.Parse(d.String("aurastatcalc1")), Aurastat2: d.String("aurastat2"), Aurastatcalc2: parser.Parse(d.String("aurastatcalc2")), Aurastat3: d.String("aurastat3"), Aurastatcalc3: parser.Parse(d.String("aurastatcalc3")), Aurastat4: d.String("aurastat4"), Aurastatcalc4: parser.Parse(d.String("aurastatcalc4")), Aurastat5: d.String("aurastat5"), Aurastatcalc5: parser.Parse(d.String("aurastatcalc5")), Aurastat6: d.String("aurastat6"), Aurastatcalc6: parser.Parse(d.String("aurastatcalc6")), Auraevent1: d.String("auraevent1"), Auraeventfunc1: d.Number("auraeventfunc1"), Auraevent2: d.String("auraevent2"), Auraeventfunc2: d.Number("auraeventfunc2"), Auraevent3: d.String("auraevent3"), Auraeventfunc3: d.Number("auraeventfunc3"), Auratgtevent: d.String("auratgtevent"), Auratgteventfunc: d.String("auratgteventfunc"), Passivestate: d.String("passivestate"), Passiveitype: d.String("passiveitype"), Passivestat1: d.String("passivestat1"), Passivecalc1: parser.Parse(d.String("passivecalc1")), Passivestat2: d.String("passivestat2"), Passivecalc2: parser.Parse(d.String("passivecalc2")), Passivestat3: d.String("passivestat3"), Passivecalc3: parser.Parse(d.String("passivecalc3")), Passivestat4: d.String("passivestat4"), Passivecalc4: parser.Parse(d.String("passivecalc4")), Passivestat5: d.String("passivestat5"), Passivecalc5: parser.Parse(d.String("passivecalc5")), Passiveevent: d.String("passiveevent"), Passiveeventfunc: d.String("passiveeventfunc"), Summon: d.String("summon"), Pettype: d.String("pettype"), Petmax: parser.Parse(d.String("petmax")), Summode: d.String("summode"), Sumskill1: d.String("sumskill1"), Sumsk1calc: parser.Parse(d.String("sumsk1calc")), Sumskill2: d.String("sumskill2"), Sumsk2calc: parser.Parse(d.String("sumsk2calc")), Sumskill3: d.String("sumskill3"), Sumsk3calc: parser.Parse(d.String("sumsk3calc")), Sumskill4: d.String("sumskill4"), Sumsk4calc: parser.Parse(d.String("sumsk4calc")), Sumskill5: d.String("sumskill5"), Sumsk5calc: parser.Parse(d.String("sumsk5calc")), Sumumod: d.Number("sumumod"), Sumoverlay: d.String("sumoverlay"), Stsuccessonly: d.Bool("stsuccessonly"), Stsound: d.String("stsound"), Stsoundclass: d.String("stsoundclass"), Stsounddelay: d.Bool("stsounddelay"), Weaponsnd: d.Bool("weaponsnd"), Dosound: d.String("dosound"), DosoundA: d.String("dosound a"), DosoundB: d.String("dosound b"), Tgtoverlay: d.String("tgtoverlay"), Tgtsound: d.String("tgtsound"), Prgoverlay: d.String("prgoverlay"), Prgsound: d.String("prgsound"), Castoverlay: d.String("castoverlay"), Cltoverlaya: d.String("cltoverlaya"), Cltoverlayb: d.String("cltoverlayb"), Cltstfunc: d.Number("cltstfunc"), Cltdofunc: d.Number("cltdofunc"), Cltprgfunc1: d.Number("cltprgfunc1"), Cltprgfunc2: d.Number("cltprgfunc2"), Cltprgfunc3: d.Number("cltprgfunc3"), Cltmissile: d.String("cltmissile"), Cltmissilea: d.String("cltmissilea"), Cltmissileb: d.String("cltmissileb"), Cltmissilec: d.String("cltmissilec"), Cltmissiled: d.String("cltmissiled"), Cltcalc1: parser.Parse(d.String("cltcalc1")), Cltcalc2: parser.Parse(d.String("cltcalc2")), Cltcalc3: parser.Parse(d.String("cltcalc3")), Warp: d.Bool("warp"), Immediate: d.Bool("immediate"), Enhanceable: d.Bool("enhanceable"), Attackrank: d.Number("attackrank"), Noammo: d.Bool("noammo"), Range: d.String("range"), Weapsel: d.Number("weapsel"), Itypea1: d.String("itypea1"), Itypea2: d.String("itypea2"), Itypea3: d.String("itypea3"), Etypea1: d.String("etypea1"), Etypea2: d.String("etypea2"), Itypeb1: d.String("itypeb1"), Itypeb2: d.String("itypeb2"), Itypeb3: d.String("itypeb3"), Etypeb1: d.String("etypeb1"), Etypeb2: d.String("etypeb2"), Anim: anim, Seqtrans: d.String("seqtrans"), Monanim: d.String("monanim"), Seqnum: d.Number("seqnum"), Seqinput: d.Number("seqinput"), Durability: d.Bool("durability"), UseAttackRate: d.Bool("UseAttackRate"), LineOfSight: d.Number("LineOfSight"), TargetableOnly: d.Bool("TargetableOnly"), SearchEnemyXY: d.Bool("SearchEnemyXY"), SearchEnemyNear: d.Bool("SearchEnemyNear"), SearchOpenXY: d.Bool("SearchOpenXY"), SelectProc: d.Number("SelectProc"), TargetCorpse: d.Bool("TargetCorpse"), TargetPet: d.Bool("TargetPet"), TargetAlly: d.Bool("TargetAlly"), TargetItem: d.Bool("TargetItem"), AttackNoMana: d.Bool("AttackNoMana"), TgtPlaceCheck: d.Bool("TgtPlaceCheck"), ItemEffect: d.Number("ItemEffect"), ItemCltEffect: d.Number("ItemCltEffect"), ItemTgtDo: d.Number("ItemTgtDo"), ItemTarget: d.Number("ItemTarget"), ItemCheckStart: d.Bool("ItemCheckStart"), ItemCltCheckStart: d.Bool("ItemCltCheckStart"), ItemCastSound: d.String("ItemCastSound"), ItemCastOverlay: d.String("ItemCastOverlay"), Skpoints: parser.Parse(d.String("skpoints")), Reqlevel: d.Number("reqlevel"), Maxlvl: d.Number("maxlvl"), Reqstr: d.Number("reqstr"), Reqdex: d.Number("reqdex"), Reqint: d.Number("reqint"), Reqvit: d.Number("reqvit"), Reqskill1: d.String("reqskill1"), Reqskill2: d.String("reqskill2"), Reqskill3: d.String("reqskill3"), Restrict: d.Number("restrict"), State1: d.String("State1"), State2: d.String("State2"), State3: d.String("State3"), Delay: d.Number("delay"), Leftskill: d.Bool("leftskill"), Repeat: d.Bool("repeat"), Checkfunc: d.Number("checkfunc"), Nocostinstate: d.Bool("nocostinstate"), Usemanaondo: d.Bool("usemanaondo"), Startmana: d.Number("startmana"), Minmana: d.Number("minmana"), Manashift: d.Number("manashift"), Mana: d.Number("mana"), Lvlmana: d.Number("lvlmana"), Interrupt: d.Bool("interrupt"), InTown: d.Bool("InTown"), Aura: d.Bool("aura"), Periodic: d.Bool("periodic"), Perdelay: parser.Parse(d.String("perdelay")), Finishing: d.Bool("finishing"), Passive: d.Bool("passive"), Progressive: d.Bool("progressive"), General: d.Bool("general"), Scroll: d.Bool("scroll"), Calc1: parser.Parse(d.String("calc1")), Calc2: parser.Parse(d.String("calc2")), Calc3: parser.Parse(d.String("calc3")), Calc4: parser.Parse(d.String("calc4")), Param1: d.Number("Param1"), Param2: d.Number("Param2"), Param3: d.Number("Param3"), Param4: d.Number("Param4"), Param5: d.Number("Param5"), Param6: d.Number("Param6"), Param7: d.Number("Param7"), Param8: d.Number("Param8"), InGame: d.Bool("InGame"), ToHit: d.Number("ToHit"), LevToHit: d.Number("LevToHit"), ToHitCalc: parser.Parse(d.String("ToHitCalc")), ResultFlags: d.Number("ResultFlags"), HitFlags: d.Number("HitFlags"), HitClass: d.Number("HitClass"), Kick: d.Bool("Kick"), HitShift: d.Number("HitShift"), SrcDam: d.Number("SrcDam"), MinDam: d.Number("MinDam"), MinLevDam1: d.Number("MinLevDam1"), MinLevDam2: d.Number("MinLevDam2"), MinLevDam3: d.Number("MinLevDam3"), MinLevDam4: d.Number("MinLevDam4"), MinLevDam5: d.Number("MinLevDam5"), MaxDam: d.Number("MaxDam"), MaxLevDam1: d.Number("MaxLevDam1"), MaxLevDam2: d.Number("MaxLevDam2"), MaxLevDam3: d.Number("MaxLevDam3"), MaxLevDam4: d.Number("MaxLevDam4"), MaxLevDam5: d.Number("MaxLevDam5"), DmgSymPerCalc: parser.Parse(d.String("DmgSymPerCalc")), EType: d.String("EType"), EMin: d.Number("EMin"), EMinLev1: d.Number("EMinLev1"), EMinLev2: d.Number("EMinLev2"), EMinLev3: d.Number("EMinLev3"), EMinLev4: d.Number("EMinLev4"), EMinLev5: d.Number("EMinLev5"), EMax: d.Number("EMax"), EMaxLev1: d.Number("EMaxLev1"), EMaxLev2: d.Number("EMaxLev2"), EMaxLev3: d.Number("EMaxLev3"), EMaxLev4: d.Number("EMaxLev4"), EMaxLev5: d.Number("EMaxLev5"), EDmgSymPerCalc: parser.Parse(d.String("EDmgSymPerCalc")), ELen: d.Number("ELen"), ELevLen1: d.Number("ELevLen1"), ELevLen2: d.Number("ELevLen2"), ELevLen3: d.Number("ELevLen3"), ELenSymPerCalc: parser.Parse(d.String("ELenSymPerCalc")), Aitype: d.Number("aitype"), Aibonus: d.Number("aibonus"), CostMult: d.Number("cost mult"), CostAdd: d.Number("cost add"), } records[record.ID] = record } if d.Err != nil { return d.Err } r.Skill.Details = records r.Debugf("Loaded %d Skill records", len(records)) return nil } func animToEnum(anim string) (d2enum.PlayerAnimationMode, error) { switch anim { case "SC": return d2enum.PlayerAnimationModeCast, nil case "TH": return d2enum.PlayerAnimationModeThrow, nil case "KK": return d2enum.PlayerAnimationModeKick, nil case "SQ": return d2enum.PlayerAnimationModeSequence, nil case "S1": return d2enum.PlayerAnimationModeSkill1, nil case "S2": return d2enum.PlayerAnimationModeSkill2, nil case "S3": return d2enum.PlayerAnimationModeSkill3, nil case "S4": return d2enum.PlayerAnimationModeSkill4, nil case "A1": return d2enum.PlayerAnimationModeAttack1, nil case "A2": return d2enum.PlayerAnimationModeAttack2, nil case "": return d2enum.PlayerAnimationModeNone, nil } // should not be reached return d2enum.PlayerAnimationModeNone, fmt.Errorf("unknown skill anim value [%s]", anim) }