HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Object Data Extractor (Alpha)

11-30-2009, 02:50 AM#1
PurplePoot
Basically, this is a preprocessor which loads object data you ask for into your map for later use. It was originally written by me, and has more recently been maintained by Bobo_The_Kodo and Deaod. The current version should be reasonably stable.

Warning: There is a nontrivial chance that I slightly messed up the syntax here, since it's been years since I actively maintained this. It should be right unless Deaod/Bobo_The_Kodo changed the syntax though, and as far as I can tell from the code they didn't.

Download

ODE 4.4 is the latest version and is stable as far as I know.

ODE is also on GitHub.

Installation

Ensure your Visual C++ is up to date.
Ensure your Java Runtime Environment is up to date.

If you are using JassNewGenPack 5d with no modifications, you can unzip everything into your JNGP folder and be ready to go.

If you are using another version of JassNewGenPack, or have modified your wehack.lua, extract everything other than wehack.lua. Afterwards, open your wehack.lua and find these lines:

Code:
	wehack.extractfile(jh_path.."jasshelper\\common.j","scripts\\common.j")
	wehack.extractfile(jh_path.."jasshelper\\Blizzard.j","scripts\\Blizzard.j")
	wehack.extractfile("war3map.j","war3map.j")
	wehack.closearchive(map)

Directly after that block, add a new line with the following code:

Code:
    wehack.runprocess("javaw -Djava.library.path=\"ode\\lib\" -jar \"ode\\ode.jar\" \"ode\" \"" .. mappath .. "\"")

Then save your wehack.lua and you're good to go.

Preprecessor Syntax

//! LoadUnitData [-noinit] [-defaults] [races=race1,race2,race3,...] [rawcodes=raw1,raw2,raw3,...] fields=field1,field2,field3,...
//! LoadItemData [-noinit] [-defaults] [classes=class1,class2,class3,...] [rawcodes=raw1,raw2,raw3,...] fields=field1,field2,field3,...

This is safe to include multiple separate calls of.

-noinit

If -noinit is used in a LoadUnitData request, any fields requested in that request will not be loaded unless they are also requested in another LoadUnitData which doesn't include -noinit.

-defaults

By default, only custom units or base units which you have modified will be loaded. With this option enabled, you'll load unmodified base units' data too.

races/classes

Restrict to only loading units from specified races or items from specific classes. Only applies to defaults.

rawcodes

Restrict to only loading units or items with specified rawcodes. Only applies to defaults

fields

The object data fields you want to load. Grimoire shows these in brackets next to the field names.

Function Syntax

If you used -noinit and need to initialize things manually, call InitExportedUnitData() or call InitExportedItemData(). If it's run multiple times it'll just do nothing. It's stored in a library which is required by every other library in the map, so you should be able to call it from pretty much anywhere.

Getter function syntax: function GetUnitType<x> takes integer unitid returns <y> or function GetItemType<x> takes integer itemid returns <y>.

<x> is the name associated with the field rawcode. These are attached below.
<y> is either integer, real, string, or boolean as appropriate.

unit suffixes

'udaa' : DefaultActiveAbility
'uhab' : HeroAbilities
'uabi' : Abilities
'utcc' : AllowCustomTeamColor
'uble' : BlendTime
'ucbs' : CastBackswing
'ucpt' : CastPoint
'urun' : RunSpeed
'uwal' : WalkSpeed
'ubpx' : ButtonPositionX
'ubpy' : ButtonPositionY
'udtm' : DeathTime
'uept' : ElevationSamplePoints
'uerd' : ElevationSampleRadius
'ufrd' : FogOfWarSampleRadius
'uubs' : GroundTexture
'ushr' : HasWaterShadow
'uico' : Icon
'ussi' : ScoreScreenIcon
'umxp' : MaxPitch
'umxr' : MaxRoll
'umdl' : Model
'uver' : ModelExtraVersions
'uocc' : OcculderHeight
'uori' : OrientationInterpolation
'uisz' : SwimProjectileImpactZ
'uimz' : ProjectileImpactZ
'ulpx' : ProjectileLaunchX
'ulsz' : SwimProjectileLaunchZ
'ulpz' : ProjectileLaunchZ
'uprw' : PropulsionWindow
'uani' : RequiredAnimationNames
'uaap' : RequiredAnimationAttachments
'ualp' : RequiredAnimationLinkNames
'ubpr' : RequiredBoneNames
'uscb' : ScaleProjectiles
'usca' : Scale
'uslz' : SelectionZ
'usew' : SelectionOnWater
'ussc' : SelectionScale
'ushu' : ShadowImage
'ushx' : ShadowImageCenterX
'ushy' : ShadowImageCenterY
'ushh' : ShadowImageHeight
'ushw' : ShadowImageWidth
'ushb' : ShadowTexture
'uspa' : SpecialArt
'utaa' : TargetArt
'utco' : TeamColor
'uclr' : RedTint
'uclg' : GreenTint
'uclb' : BlueTint
'ulos' : UseExtendedLineOfSight
'uacq' : AcquisitionRange
'uarm' : ArmorType
'ubs1' : BackswingPoint1
'udp1' : DamagePoint1
'ua1f' : AreaOfEffectFull1
'ua1h' : AreaOfEffectMedium1
'ua1q' : AreaOfEffectSmall1
'ua1p' : AreaOfEffectTargets1
'ua1t' : AttackType1
'ua1c' : Cooldown1
'ua1b' : DamageBase1
'uhd1' : DamageFactorMedium1
'uqd1' : DamageFactorSmall1
'udl1' : DamageLossFactor1
'ua1d' : DamageNumberOfDice1
'ua1s' : DamageSidesPerDie1
'usd1' : DamageSpillDistance1
'usr1' : DamageSpillRadius1
'udu1' : DamageUpgradeAmount1
'utc1' : MaximumTargets1
'uma1' : ProjectileArc1
'ua1m' : ProjectileArt1
'umh1' : ProjectileHoming1
'ua1z' : ProjectileSpeed1
'ua1r' : Range1
'urb1' : RangeMotionBuffer1
'uwu1' : ShowUI1
'ua1g' : TargetsAllowed1
'ucs1' : WeaponSound1
'ua1w' : WeaponType1
'ubs2' : BackswingPoint2
'udp2' : DamagePoint2
'ua2f' : AreaOfEffectFull2
'ua2h' : AreaOfEffectMedium2
'ua2q' : AreaOfEffectSmall2
'ua2p' : AreaOfEffectTargets2
'ua2t' : AttackType2
'ua2c' : Cooldown2
'ua2b' : DamageBase2
'uhd2' : DamageFactorMedium2
'uqd2' : DamageFactorSmall2
'udl2' : DamageLossFactor2
'ua2d' : DamageNumberOfDice2
'ua2s' : DamageSidesPerDie2
'usd2' : DamageSpillDistance2
'usr2' : DamageSpillRadius2
'udu2' : DamageUpgradeAmount2
'utc2' : MaximumTargets2
'uma2' : ProjectileArc2
'ua2m' : ProjectileArt2
'umh2' : ProjectileHoming2
'ua2z' : ProjectileSpeed2
'ua2r' : Range2
'urb2' : RangeMotionBuffer2
'uwu2' : ShowUI2
'ua2g' : TargetsAllowed2
'ucs2' : WeaponSound2
'ua2w' : WeaponType2
'uaen' : AttacksEnabled
'udea' : DeathType
'udef' : DefenseBase
'udty' : DefenseType
'udup' : DefenseUpgradeBonus
'uamn' : MinimumAttackRange
'utar' : TargetedAs
'udro' : DropItemsOnDeath
'ucam' : CategoryCampaign
'uspe' : CategorySpecial
'uhos' : DisplayAsNeutralHostile
'utss' : HasTilesetSpecificData
'uine' : PlaceableInEditor
'util' : Tilesets
'uuch' : UseClickHelper
'urpo' : GroupSeparationEnabled
'urpg' : GroupSeparationGroupNumber
'urpp' : GroupSeparationParameter
'urpr' : GroupSeparationPriority
'umvh' : FlyHeight
'umvf' : MinimumHeight
'umvs' : SpeedBase
'umas' : SpeedMaximum
'umis' : SpeedMinimum
'umvr' : TurnRate
'umvt' : MoveType
'uabr' : AIPlacementRadius
'uabt' : AIPlacementType
'ucol' : CollisionSize
'upat' : PathingMap
'upar' : PlacementPreventedBy
'upap' : PlacementRequires
'upaw' : PlacementRequiresWaterRadius
'ubsl' : BuildSound
'ulfi' : SoundLoopFadeInRate
'ulfo' : SoundLoopFadeOutRate
'umsl' : MoveSound
'ursl' : RandomSound
'usnd' : SoundSet
'uagp' : AgilityPerLevel
'ubld' : BuildTime
'uibo' : CanBeBuiltOn
'ucbo' : CanBuildOn
'ufle' : CanFlee
'ufoo' : FoodCost
'ufma' : FoodProduced
'ufor' : FormationRank
'ubba' : GoldBountyBase
'ubdi' : GoldBountyNumberOfDice
'ubsi' : GoldBountySidesPerDie
'ugol' : GoldCost
'uhhd' : HideHeroDeathMessage
'uhhb' : HideHeroInterfaceIcon
'uhhm' : HideHeroMinimapDisplay
'uhom' : HideMinimapDisplay
'uhpm' : HitPointsMaximum
'uhpr' : HitPointsRegeneration
'uhrt' : HitPointsRegenerationType
'uinp' : IntelligencePerLevel
'ubdg' : IsABuilding
'ulev' : Level
'ulba' : LumberBountyBase
'ulbd' : LumberBountyNumberOfDice
'ulbs' : LumberBountySidesPerDie
'ulum' : LumberCost
'umpi' : ManaInitialAmount
'umpm' : ManaMaximum
'umpr' : ManaRegeneration
'unbm' : ShowNeutralBuildingIcon
'unbr' : ValidAsRandomNeutralBuilding
'upoi' : PointValue
'upra' : PrimaryAttribute
'upri' : Priority
'urac' : Race
'ugor' : RepairGoldCost
'ulur' : RepairLumberCost
'urtm' : RepairTime
'usid' : SightRadiusDay
'usin' : SightRadiusNight
'usle' : Sleeps
'uagi' : StartingAgility
'uint' : StartingIntelligence
'ustr' : StartingStrength
'usma' : StockMaximum
'usrg' : StockReplenishInterval
'usst' : StockStartDelay
'ustp' : StrengthPerLevel
'ucar' : TransportedSize
'utyp' : UnitClassification
'udep' : DependencyEquivalents
'urva' : HeroRevivalLocations
'umki' : ItemsMade
'usei' : ItemsSold
'ureq' : Requirements
'urqa' : RequirementsLevels
'urq1' : RequirementsTier2
'urq2' : RequirementsTier3
'urq3' : RequirementsTier4
'urq4' : RequirementsTier5
'urq5' : RequirementsTier6
'urq6' : RequirementsTier7
'urq7' : RequirementsTier8
'urq8' : RequirementsTier9
'urqc' : RequirementsTiersUsed
'ubui' : StructuresBuilt
'ures' : ResearchesAvailable
'urev' : RevivesDeadHeroes
'useu' : UnitsSold
'utra' : UnitsTrained
'uupt' : UpgradesTo
'upgr' : UpgradesUsed
'ides' : Description
'uhot' : Hotkey
'unam' : Name
'unsf' : NameEditorSuffix
'upro' : ProperNames
'upru' : ProperNamesUsed
'uawt' : AwakenTooltip
'utip' : Tooltip
'utub' : Ubertip
'utpr' : ReviveTooltip



item suffixes

'iabi' : Abilities
'iarm' : ArmorType
'iico' : Icon
'ubpx' : ButtonPositionX
'ubpy' : ButtonPositionY
'icla' : Class
'iclb' : ColorBlue
'iclg' : ColorGreen
'iclr' : ColorRed
'icid' : CooldownGroup
'ides' : Description
'idrp' : DropsOnDeath
'idro' : Droppable
'ifil' : Model
'igol' : GoldCost
'uhot' : Hotkey
'ihtp' : Health
'iicd' : IgnoreCooldown
'ilev' : Level
'ilum' : LumberCost
'imor' : IsTransformable
'unam' : Name
'ilvo' : UnclassifiedLevel
'ipaw' : IsPawnable
'iper' : IsPerishable
'iprn' : IsRandomChoice
'ipow' : IsPowerup
'ipri' : Priority
'ureq' : Requirements
'urqa' : RequiredLevels
'isca' : Scale
'isel' : IsSellable
'issc' : SelectionSize
'isto' : MaximumStock
'istr' : StockReplenishInterval
'isst' : StartingStock
'utip' : Tooltip
'utub' : Ubertip
'iusa' : IsUsable
'iuse' : Uses



Comments

This is mostly Java, although there's a bit of C++ for the JNI to interface with JStormLib32/64.dll. Thanks to Deaod the code is basically redone from scratch to a far more usable and less temporary state than the initial stuff, and most of the earlier bugs are now fixed. Not tested on huge maps, but it barely affected save times on a fairly large map I tested in and shouldn't affect save times at all if you don't call //! loadunitdata.

Example uses:
  • Replace all the hacked together "GetUnitGoldCost"/"GetUnitLumberCost"/"GetUnitCollisionSize"/etc systems with something more reliable.
  • Make systems such as inventory systems which use images and trackables much less painful to put data into (when items, in this case, can be accessed).
  • A projectile system.
  • A custom attack system.
  • A buff system or something (when abilities or buffs can be accessed).

To Do:
  • Items, Abilities [, Buffs?]
  • Bugfixes and optimization.
  • Make the program automatically check if Warcraft has been updated and replace the data files accordingly.
  • Other stuff?

Also includes a demo map.

Changelog

For now it's in the pastebin entry where the preview builds are.
Attached Files
File type: w3mTestObjDataExporter14.w3m (16.2 KB)
File type: zipode-44.zip (1.6 MB)
File type: zipode-44-src.zip (3.9 MB)
11-30-2009, 08:52 AM#2
Anitarf
Quote:
Make default units which have not been modified loadable.
I'm not sure if that is needed, or in fact desired as it may increase loading time.

Can we have multiple //! LoadUnitData calls in a map, or is that a one-time thing?
11-30-2009, 09:10 AM#3
TriggerHappy
I was told you were making this. Nice.
11-30-2009, 12:41 PM#4
grim001
Very nice. From your description, this tool does everything I was hoping it would. I'm going to give it some testing tonight.
11-30-2009, 01:49 PM#5
Furby
Since I was told about this I couldn't wait.. finally it has come. :)
Quote:
Originally Posted by PurplePoot
//! LoadUnitData [-noinit] fld1 fld2 fld3 fld4 fld5 ...
This will actually load data of all customed units in OE? Or.. ?

Quote:
Originally Posted by PurplePoot
(Grimoire displays these beside the field name in brackets)
You might want to add this to first post.
11-30-2009, 05:19 PM#6
PurplePoot
Quote:
Originally Posted by Anitarf
I'm not sure if that is needed, or in fact desired as it may increase loading time.
You would have to manually specify it (For example, race=human). However, if there is no demand I won't bother.

Quote:
Originally Posted by Anitarf
Can we have multiple //! LoadUnitData calls in a map, or is that a one-time thing?
No. Do you have a reason to? I could implement that relatively easily, but I just didn't see a need. It could also add some ambiguity (what if one had -noinit and the other didn't, for example?).

Quote:
Originally Posted by furby777
This will actually load data of all customed units in OE? Or.. ?
Exactly (of the fields you specify).

Quote:
Originally Posted by furby777
You might want to add this to first post.
Thanks for the image; will do.

--

I should also note that the current syntax will be slightly changed in the next version to allow for easier integration of more object types (ExportedObjectData will become ExportedUnitData, ExportedItemData, etc, in every occurance of the word).
11-30-2009, 05:58 PM#7
Furby
Btw, will each function return data in certain type? For example call GetUnitTypeDamageBase1 will return real and call GetUnitTypeIcon will return string?
11-30-2009, 06:14 PM#8
Rising_Dusk
Quote:
Originally Posted by PurplePoot
No. Do you have a reason to? I could implement that relatively easily, but I just didn't see a need. It could also add some ambiguity (what if one had -noinit and the other didn't, for example?).
So that multiple scripts can get different pieces of data from the Object Editor as necessary, instead of just importing everything and picking from that what is needed. It would be faster being able to have multiple calls to it. (So it runs similar to ObjectMerger)
11-30-2009, 06:20 PM#9
PurplePoot
Fair enough. How would you suggest handling ambiguities such as the one mentioned above, then?

Perhaps do it if any one of them had it set?

EDIT: Done with the above method.

EDIT2:

Quote:
Originally Posted by furby777
Btw, will each function return data in certain type? For example call GetUnitTypeDamageBase1 will return real and call GetUnitTypeIcon will return string?
They return the type that makes sense (integer if the field is an integer, real if the field is a real or unreal, boolean if the field is a boolean, and a string otherwise). GetUnitTypeDamageBase1 is in fact an integer (refer to the object editor!).

Lists of data are generally separated with commas, so GetUnitTypeAbilities('blah') might look like "A001,A005".
11-30-2009, 10:29 PM#10
Kwah
Sounds handy. Will test once fix JNGP installation.
12-01-2009, 04:51 AM#11
Rising_Dusk
Quote:
Originally Posted by PurplePoot
Perhaps do it if any one of them had it set?
What is the advantage of not initializing them right on map init anyways? What sort of delay/lag is experienced when loading the data for a lot of types?
Quote:
Originally Posted by PurplePoot
EDIT: Done with the above method.
Have you made it work properly for the case where multiple libraries request the same data field? Furthermore, let's say a map only needs access to, say, damage base or armor base. Will they be able to access just those fields without loading all of the data for the types?
12-01-2009, 05:34 AM#12
ploks
I might be the only one but access to Custom Game Constants would be nice! Anyway I've been waiting for something like this. Keep the good work up!
12-01-2009, 05:52 AM#13
TriggerHappy
Quote:
Originally Posted by ploks
I might be the only one but access to Custom Game Constants would be nice! Anyway I've been waiting for something like this. Keep the good work up!

hmm.

That could be useful inside static ifs, but nowhere else because you can just manually do it.
12-01-2009, 06:06 AM#14
Rising_Dusk
Eh, I probably wouldn't use it for a gameplay constant extractor. Really, the constants you can just declare as constant globals and be done with it. It's not like unit data where 100 unit types each have a different value for X field.
12-01-2009, 07:04 AM#15
Furby
Yep, I totally agree with Dusk. :) I see no reason to use for game constants.

But, I can't wait until you implement ability extractor.