package data import ( "code.ur.gs/lupine/ordoor/internal/util/asciiscan" ) type ActionPointEnum int type SettingEnum int type TransitionFrameEnum int type SquadTypeEnum int // just for the multiplayer choose units menu type VehicleTypeEnum int // just for the multiplayer choose units screen type OptionEnum int // differs from settings in that these are defaults changeable from the UI type SpellEnum int type AIPriorityEnum int // FIXME: no idea what this is for type RngRangeEnum int // VEHICLE_WALK_TRANSITION_FRAME entries const ( APCastSpell ActionPointEnum = 0 APWalk = 1 APRun = 2 APTurn = 3 APCrouch = 4 APStand = 5 APOpenDoor = 6 APDropItem = 7 APPickupItem = 8 APThrowItem = 9 APUseMedikit = 10 APUseScanner = 11 APJump = 12 APThrowGrenade = 13 APHalfTurn = 14 APToClearJammedWeapon = 15 APHandToHandRound = 16 APToUseSwitch = 17 APToUseKey = 18 APToBoardDisembark = 19 APWhenOnFire = 20 APWhenBroken = 21 APMax = 22 SettingOccasionalSoundPercent SettingEnum = 0 SettingOccasionalMovementSound = 1 SettingFullJumpFuel = 2 SettingMaxJumpDistance = 3 SettingFlyFramesPerCell = 4 SettingPowerArmorRating = 5 SettingTerminatorArmorRating = 6 SettingBloodThirsterArmorRating = 7 SettingDemonicArmorRating = 8 SettingPrimitiveArmorRating = 9 SettingHorrorArmorRating = 10 SettingArmorDice = 11 SettingJumpPixelsPerFrame = 12 SettingCharacterAnimationDelay = 13 SettingVehicleAnimationDelay = 14 SettingLoopingEffectsDelay = 15 SettingFireAnimationDelay = 16 SettingCharacterFireTransparency = 17 SettingMissileDrawOffset = 18 // pixels per missing piece SettingWeaponJamPercent = 19 // to two decimal places SettingScanFrequency = 20 SettingCoverSearchRadius = 21 SettingDialogAutoCloseTime = 22 SettingPointBlankBallisticSkillBonus = 23 SettingPointBlankRange = 24 SettingMinimumOverwatchShotPercent = 25 SettingMultipleSekectDragTolerance = 26 SettingStandingGuardPostRadius = 27 SettingMaxDemonFlyDistance = 28 SettingSpellLoopingVolume = 29 // percentage, 0 decimal places SettingPercentOfChaosInSecondaryQuadrant = 30 SettingNumberOfRandomCrates = 31 SettingMax = 32 TFDeletedVehicle TransitionFrameEnum = 0 TFUltraRhino = 1 TFUltraPredator = 2 TFUltraLandSpeeder = 3 TFUltraDreadnought = 4 TFChaosRhino = 5 TFChaosPredator = 6 TFChaosDreadnought = 7 TFMax = 8 SquadTerminator SquadTypeEnum = 0 SquadTactical = 1 SquadAssault = 2 SquadDevastator = 3 SquadChaos = 4 SquadChaosKhorne = 5 SquadChaosTerminator = 6 SquadChaosCultise = 7 SquadLibrarian = 8 SquadTechmarine = 9 SquadApothecary = 10 SquadChaplain = 11 SquadCaptain = 12 SquadChaosLord = 13 SquadChaosChaplain = 14 SquadChaosSorcerer = 15 SauadChaosBlodThirster = 16 SquadChaosBlootLetter = 17 SquadChaosFleshHound = 18 SquadChaosLordOfChange = 19 SquadChaosFlamer = 20 SquadChaosPinkHorror = 21 SquadChaosBlueHorror = 22 SquadMax = 23 VehicleUltraRhino VehicleTypeEnum = 0 VehicleUltraPredator = 1 VehicleUltraLandSpeeder = 2 VehicleUltraDreadnought = 3 VehicleChaosRhino = 4 VehicleChaosPredator = 5 VehicleChaosDreadnought = 6 VehicleMax = 7 OptionMovies OptionEnum = 0 OptionMusic = 1 OptionCombatVoices = 2 OptionGrid = 3 OptionShowPaths = 4 OptionPointSave = 5 OptionAutoCutLevel = 6 OptionShowUnitAnimations = 7 OptionCombatResolution = 8 OptionMusicVolume = 9 // percentage, 0df OptionSoundEffectsVolume = 10 // percentage, 0df OptionUnitAnimationSpeed = 11 // percentage, 0df, see CHARCTER ANIMATION DELAY / VEHICLE ANIMATION DELAY for worst case value OptionEffectAnimationSpeed = 12 // percentage, 0d, see LOOPING_EFFECTS_DELAY for worst case value OptionMax = 13 SpellHellfire SpellEnum = 0 SpellLightningArc = 1 SpellGate = 2 SpellAssail = 3 SpellDisplacement = 4 SpellMachineCurse = 5 SpellScan = 6 SpellQuickening = 7 SpellStrengthOfMind = 8 SpellSmite = 9 SpellIronArm = 10 SpellSalamandar = 11 SpellTeleport = 12 SpellPsychicShield = 13 SpellDestroyDemon = 14 SpellHolocaust = 15 SpellScourge = 16 SpellPurge = 17 SpellAuraOfFire = 18 SpellVortex = 19 SpellStormOfWrath = 20 SpellAuraOfFortitude = 21 SpellPinkFireOfTzeentch = 22 SpellBoltOfChange = 23 SpellTzeentchFireStore = 24 SpellMax = 25 AIPrioritySpecialCharacter = 0 AIPriorityVehicle = 1 AIPriorityTerminator = 2 AIPriorityHeavyWeapon = 3 AIPriorityRegular = 4 AIPriorityCultist = 5 AIPriorityMax = 6 RngRangeVehicleHillHeight RngRangeEnum = 0 RngRangeVehicleHillWidth = 1 RngRangeVehicleHillDensity = 2 RngRangeVehicleLargeObjectDensity = 3 RngRangeVehicleSmallObjectDensity = 4 RngRangeNoVehicleHillHeight = 5 RngRangeNoVehicleHillWidth = 6 RngRangeNoVehicleHillDensity = 7 RngRangeNoVehicleLargeObjectDensity = 8 RngRangeNoVehicleSmallObjectDensity = 9 RngRangeMax = 10 // FIXME: is this really a hardcoded value? NumCampaignScenarios = 15 ) type Generic struct { ActionPoints map[ActionPointEnum]int Settings map[SettingEnum]int VehicleWalkTransitionFrames map[TransitionFrameEnum]CompassPoints MPChooseUnitSquadLimits map[SquadTypeEnum]int // I'm assuming this is to do with MP becauses squads are. I could be wrong. MPChooseVehicleLimits map[VehicleTypeEnum]int Options map[OptionEnum]int CampaignMaps []string CampaignEndMissionWavs []string AICoherentForce int // Range that defnines a coherent for for the AI. No idea AISpellDeltaPriorityWeights map[SpellEnum]int // AI delta priority weights for each spell AIPriority map[AIPriorityEnum]int AICommandInfiniteLoopCounterWatermark int // Messing with this can cripple the API... RngRanges map[RngRangeEnum]Range } // TODO: consume these values from the file func LoadGeneric(filename string) (*Generic, error) { s, err := asciiscan.New(filename) if err != nil { return nil, err } defer s.Close() out := &Generic{ ActionPoints: make(map[ActionPointEnum]int), Settings: make(map[SettingEnum]int), VehicleWalkTransitionFrames: make(map[TransitionFrameEnum]CompassPoints), MPChooseUnitSquadLimits: make(map[SquadTypeEnum]int), MPChooseVehicleLimits: make(map[VehicleTypeEnum]int), Options: make(map[OptionEnum]int), AISpellDeltaPriorityWeights: make(map[SpellEnum]int), AIPriority: make(map[AIPriorityEnum]int), RngRanges: make(map[RngRangeEnum]Range), } // Various action point values, first to last for ap := ActionPointEnum(0); ap < APMax; ap++ { val, err := s.ConsumeInt() if err != nil { return nil, err } out.ActionPoints[ap] = val } // Other miscellaneous data fields, first to last for setting := SettingEnum(0); setting < SettingMax; setting++ { val, err := s.ConsumeInt() if err != nil { return nil, err } out.Settings[setting] = val } // Vehicle walk transition frames. Whatever they are. for tf := TransitionFrameEnum(0); tf < TFMax; tf++ { val, err := consumeCompassPoints(s) if err != nil { return nil, err } out.VehicleWalkTransitionFrames[tf] = val } for st := SquadTypeEnum(0); st < SquadMax; st++ { val, err := s.ConsumeInt() if err != nil { return nil, err } out.MPChooseUnitSquadLimits[st] = val } for vt := VehicleTypeEnum(0); vt < VehicleMax; vt++ { val, err := s.ConsumeInt() if err != nil { return nil, err } out.MPChooseVehicleLimits[vt] = val } for op := OptionEnum(0); op < OptionMax; op++ { val, err := s.ConsumeInt() if err != nil { return nil, err } out.Options[op] = val } for i := 0; i < NumCampaignScenarios; i++ { val, err := s.ConsumeString() if err != nil { return nil, err } out.CampaignMaps = append(out.CampaignMaps, val) } for i := 0; i < NumCampaignScenarios; i++ { val, err := s.ConsumeString() if err != nil { return nil, err } // FIXME: "none" is a special-case value here out.CampaignEndMissionWavs = append(out.CampaignEndMissionWavs, val) } out.AICoherentForce, err = s.ConsumeInt() if err != nil { return nil, err } for sp := SpellEnum(0); sp < SpellMax; sp++ { val, err := s.ConsumeInt() if err != nil { return nil, err } out.AISpellDeltaPriorityWeights[sp] = val } for ai := AIPriorityEnum(0); ai < AIPriorityMax; ai++ { val, err := s.ConsumeInt() if err != nil { return nil, err } out.AIPriority[ai] = val } out.AICommandInfiniteLoopCounterWatermark, err = s.ConsumeInt() if err != nil { return nil, err } for rg := RngRangeEnum(0); rg < RngRangeMax; rg++ { val, err := consumeRange(s) if err != nil { return nil, err } out.RngRanges[rg] = val } return out, nil }