1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-11-16 01:17:10 -05:00
OpenDiablo2/d2core/d2records/skill_details_loader.go
presiyan-ivanov 7661b81576
Initial left & right skill select panel implementation. HeroSkill serialization cleanup. (#783)
- Clicking the active left/right skill now opens a skill select panel.
Only the available skills for the hero, which are valid for the panel type are shown.
Clicking on a skill from the skill select panel makes it the new active skill for the hero.

- Hovering a skill in the skill select panel shows the skill name +
skill description.

- New command which learns all skills for a specific
class(not persisted to a save file yet) - e.g. `learnskills ama` will learn
skills for the Amazon class.

- Initialize HeroSkill.shallowHeroSkill struct in the hero state factory, so we can use it
when we serialize the HeroSkill to packets/game save files.

- The parsed Skill.ListRow is now a number instead  of string.

Co-authored-by: Presiyan Ivanov <presiyan-ivanov@users.noreply.github.com>
2020-10-22 16:53:18 -04:00

322 lines
13 KiB
Go

package d2records
import (
"log"
"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)
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: animToEnum(d.String("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
log.Printf("Loaded %d Skill records", len(records))
return nil
}
func animToEnum(anim string) d2enum.PlayerAnimationMode {
switch anim {
case "SC":
return d2enum.PlayerAnimationModeCast
case "TH":
return d2enum.PlayerAnimationModeThrow
case "KK":
return d2enum.PlayerAnimationModeKick
case "SQ":
return d2enum.PlayerAnimationModeSequence
case "S1":
return d2enum.PlayerAnimationModeSkill1
case "S2":
return d2enum.PlayerAnimationModeSkill2
case "S3":
return d2enum.PlayerAnimationModeSkill3
case "S4":
return d2enum.PlayerAnimationModeSkill4
case "A1":
return d2enum.PlayerAnimationModeAttack1
case "A2":
return d2enum.PlayerAnimationModeAttack2
case "":
return d2enum.PlayerAnimationModeNone
default:
log.Fatalf("Unknown skill anim value [%s]", anim)
}
// should not be reached
return d2enum.PlayerAnimationModeNone
}