UnofficialCrusaderPatch / UnofficialCrusaderPatch2

Unofficial balancing patch installer for Stronghold Crusader 1
MIT License
429 stars 60 forks source link

unit indices #271

Open ngc92 opened 5 years ago

ngc92 commented 5 years ago

Unit IDs from some old experimentation of mine. Should extend the list in Unit.cs quite a bit

TROOP_INDICES.peasant   = 1
TROOP_INDICES.burning_man   = 2
TROOP_INDICES.lumberjack    = 3
TROOP_INDICES.fletcher  = 4
TROOP_INDICES.tunneler  = 5
TROOP_INDICES.hunter    = 6
--TROOP_INDICES.???     = 7
--TROOP_INDICES.???     = 8
--TROOP_INDICES.??? = 9
--TROOP_INDICES.??? = 10
--TROOP_INDICES.??? = 11
--TROOP_INDICES.??? = 12
--TROOP_INDICES.??? = 13
--TROOP_INDICES.??? = 14
TROOP_INDICES.child = 15
TROOP_INDICES.baker = 16
TROOP_INDICES.woman = 17
TROOP_INDICES.poleturner    = 18
TROOP_INDICES.smith = 19
TROOP_INDICES.armorer   = 20
TROOP_INDICES.tanner    = 21
TROOP_INDICES.archer    = 22
TROOP_INDICES.xbow      = 23
TROOP_INDICES.spear     = 24
TROOP_INDICES.pike      = 25
TROOP_INDICES.mace      = 26
TROOP_INDICES.sword     = 27
TROOP_INDICES.knight    = 28
TROOP_INDICES.ladder    = 29
TROOP_INDICES.engineer  = 30
--TROOP_INDICES.??? = 31
--TROOP_INDICES.??? = 32
TROOP_INDICES.priest    = 33
--TROOP_INDICES.??? = 34
TROOP_INDICES.drunk = 35
TROOP_INDICES.innkeep   = 36
TROOP_INDICES.monk      = 37
--TROOP_INDICES.??? = 38
TROOP_INDICES.catapult  = 39
TROOP_INDICES.trebuchet = 40
TROOP_INDICES.manguel   = 41
--TROOP_INDICES.??? = 42
--TROOP_INDICES.??? = 43
TROOP_INDICES.antelope  = 44
TROOP_INDICES.lion      = 45
TROOP_INDICES.rabbit    = 46
TROOP_INDICES.camel     = 47
--TROOP_INDICES.???     = 48
--TROOP_INDICES.???     = 49
TROOP_INDICES.siege_tent= 50
--TROOP_INDICES.??? = 51
--TROOP_INDICES.??? = 52
TROOP_INDICES.fireman   = 53
TROOP_INDICES.ghost     = 54
TROOP_INDICES.lord      = 55
TROOP_INDICES.lady      = 56
TROOP_INDICES.chester   = 57
TROOP_INDICES.stower    = 58
TROOP_INDICES.ram       = 59
TROOP_INDICES.shield    = 60
TROOP_INDICES.ballista  = 61
TROOP_INDICES.chicken   = 62
--TROOP_INDICES.??? = 63
--TROOP_INDICES.??? = 64
TROOP_INDICES.juggler   = 65
TROOP_INDICES.fire_eater= 66
TROOP_INDICES.dog       = 67
--TROOP_INDICES.???     = 68
--TROOP_INDICES.???     = 69
TROOP_INDICES.aarcher   = 70
TROOP_INDICES.slave     = 71
TROOP_INDICES.slinger   = 72
TROOP_INDICES.assassin  = 73
TROOP_INDICES.rarcher   = 74
TROOP_INDICES.asword    = 75
TROOP_INDICES.thrower   = 76
TROOP_INDICES.fballista = 77
YouMoMCallME commented 5 years ago

@ngc92 Your help will greatly help the development patch . Thank ! I think @Sh0wdown will be happy.

ByBurton commented 5 years ago

Hey @ngc92 thank you for this list!!! I am gonna test those values asap!!!

molchknolle commented 5 years ago

Wow, thank you so much, this is exactly the kind of thing I was hoping for with my post!! In combination with my own experiments, this allows me to provide the addresses in the exe for the health values of all units. I'm sure some people here already have a list like this, otherwise the patch would probably not be possible, but I hope it is still of help to some:

TROOP_INDICES.archer = 0x74E9B0; Nr. 3 TROOP_INDICES.xbow = 0x74E9B0; Nr. 4 TROOP_INDICES.spear = 0x74E9C0; Nr. 1 TROOP_INDICES.pike = 0x74E9C0; Nr. 2 TROOP_INDICES.mace = 0x74E9C0; Nr. 3 TROOP_INDICES.sword = 0x74E9C0; Nr. 4 TROOP_INDICES.knight = 0x74E9D0; Nr. 1 TROOP_INDICES.ladder = 0x74E9D0; Nr. 2 TROOP_INDICES.builder = 0x74E9D0; Nr. 3 TROOP_INDICES.monk = 0x74E9F0; Nr. 2 TROOP_INDICES.catapult = 0x74E9F0; Nr. 4 TROOP_INDICES.trebuchet = 0x74EA00; Nr. 1 TROOP_INDICES.manguel = 0x74EA00; Nr. 2 TROOP_INDICES.lion = 0x74EA10 ; Nr. 2 TROOP_INDICES.siege_tent = 0x74EA20; Nr. 3 TROOP_INDICES.lord = 0x74EA30; Nr. 4 TROOP_INDICES.stower = 0x74EA40; Nr. 3 TROOP_INDICES.ram = 0x74EA40; Nr. 4 TROOP_INDICES.shield = 0x74EA50; Nr. 1 TROOP_INDICES.ballista = 0x74EA50; Nr. 2 TROOP_INDICES.dog = 0x74EA60; Nr. 4 TROOP_INDICES.aarcher = 0x74EA70; Nr. 3 TROOP_INDICES.slave = 0x74EA70; Nr. 4 TROOP_INDICES.slinger = 0x74EA80; Nr. 1 TROOP_INDICES.assassin = 0x74EA80; Nr. 2 TROOP_INDICES.rarcher = 0x74EA80; Nr. 3 TROOP_INDICES.asword = 0x74EA80; Nr. 4 TROOP_INDICES.thrower = 0x74EA90; Nr. 1 TROOP_INDICES.fballista = 0x74EA90; Nr. 2

For those who don't know, each address, for example 0x74EA30, refers to one 16-hex-number line in the hex editor. I'm not really well versed in the technical details, so I can't explain the background - but, on the practical side of things, each line in this section holds the health values for 4 units and each value in turn is made up of 4 hex-numbers, like 10 27 00 00, where the third one is usually 00 and the last one always (actually reduces health in a weird way if set to another value). As far as I understand, the numbers' places are reversed, so 10 27 00 ist actually 00 27 10, or, in decimal, 10,000.

So, for example, if you open your exe, go to address 0x74E9B0 and set the third set of hex numbers to FF FF FF 00, you'll get near-immortal archers, while setting it to all zeros makes them die from one hit of anything.

Could anyone provide a similar list for unit/building costs, and/or damage and range values? Even just knowing the general area in the exe would be of much help. I've benn waiting for triple-range firethrowers, cow-throwers, invisible knights and so on basically since my childhood...!

... just thought of it: the addresses might vary by stronghold version in some way, I'm not sure about that!

ngc92 commented 5 years ago

some more data from my Cheat Engine lua scripts. I think quite a bit overlaps with what is already in this path, but maybe you find something useful. These are the addresses within the running process, I dont know how they translate into the exe.

UNIT_COST_BASE = 0x00AB8114
UNIT_COST_INDICES = {}
UNIT_COST_INDICES.archer = 0
UNIT_COST_INDICES.xbow = 1
UNIT_COST_INDICES.spear = 2
UNIT_COST_INDICES.pike = 3
UNIT_COST_INDICES.mace = 4
UNIT_COST_INDICES.sword = 5
UNIT_COST_INDICES.knight = 6
UNIT_COST_INDICES.aarcher = 10
UNIT_COST_INDICES.slave = 11
UNIT_COST_INDICES.slinger = 12
UNIT_COST_INDICES.assassin = 13
UNIT_COST_INDICES.rarcher = 15

-- gold cost
function getUnitCostAddress(unit)
    return UNIT_COST_BASE + 4 * UNIT_COST_INDICES[unit]
end

UNIT_HP_BASE_ADDRESS = 0xB4D960

function getHPAddress(unit)
    return UNIT_HP_BASE_ADDRESS + 4 * TROOP_INDICES[unit]
end

-- projectile damage
function getArrowDamageAddress(target)
    -- archers
    local base = 0xB4DAA0
    return base + 4 * TROOP_INDICES[target]
end

function getStoneDamageAddress(target)
    -- slingers
    local base = 0xB4DBE0
    return base + 4 * TROOP_INDICES[target]
end

function getBoltDamageAddress(target)
    -- crossbow
    local base = 0xB4DD20
    return base + 4 * TROOP_INDICES[target]
end

function getDamageAddress(attacker, attacked)
-- knight vs peasant:   0xB50164
-- knight vs sword      0xB501CC
-- sword vs sword       0xB5008C
-- distance (byte): 320 = 0x140
-- distance          80 =  0x50

    local knight_base   = 0xB50160;
    local entry_size    = 0x140;
    local attacker_base = (TROOP_INDICES[attacker] - TROOP_INDICES.knight) *
                                                        entry_size + knight_base
    local offset = 4 * TROOP_INDICES[attacked]

    return attacker_base + offset
end

PlayerOffset = 0x39F4

function getMoneyAddress(player)
         local P1 = 0x115ECF0
         return P1 + (player-1)*PlayerOffset
end

function getPopularityAddress(player)
         local P1 = 0x115e844
         return P1 + (player-1)*PlayerOffset
end

function getMenCountAddress(type, player)
         local P1 = 0x1160844
         return P1 + TROOP_INDICES[type]*4 + (player-1)*PlayerOffset
end

BUILDING_INDICES = {}
BUILDING_INDICES.round_tower = 78
BUILDING_INDICES.square_tower = 77
BUILDING_INDICES.defense_tower = 76
BUILDING_INDICES.out_tower = 75
BUILDING_INDICES.guard_tower = 74

BUILDING_MATERAL_INDICES = {}
BUILDING_MATERAL_INDICES.wood = 0
BUILDING_MATERAL_INDICES.stone = 1
BUILDING_MATERAL_INDICES.iron = 2
BUILDING_MATERAL_INDICES.pitch = 3
BUILDING_MATERAL_INDICES.gold = 4
BUILDING_MATERAL_INDICES.count = 5

function getBuildingHPAddress(building)
         local base = 0x005B9218;
         return BUILDING_INDICES[building] * 4 + base
end

function getBuildingCostAddress(building, material)
         local ref = 0x11242f0
         local base = ref + 4 * BUILDING_MATERAL_INDICES.count * (BUILDING_INDICES[building] - BUILDING_INDICES.square_tower)
         return base + 4 * BUILDING_MATERAL_INDICES[material]
end
molchknolle commented 5 years ago

Wow, I didn't know cheatengine could do/ be used for something as detailed as that! Those indices were really useful, they allowed me to find build costs for units and buildings as well as unit move speeds. I could make lists of those too if anyone is interested. Still waiting and looking for damage and range!

ByBurton commented 5 years ago

That cheat engine stuff might be interesting for @Sh0wdown or no. I have no idea exactly. But I think he already knows about how to get costs, and probably about the building hp. Although it can be quite useful for balance changes in the future. Do you know where the current population is stored?

ngc92 commented 5 years ago

OK, so I think the absolute addresses in my post are not valid for 1.41, but the relative structure should still be the same.

To get the address of the current population, you can open a map in the editor, set a military unit, turn it into a peasant and let cheat engine scan for an entry of 1, then add more peasants and rescan until you have narrowed it down. However, I could not manage it to get below 5 addresses which all seem to contain the current population, but it should give you a starting point

ByBurton commented 5 years ago

But is that not the count of peasants? I mean, does it include workers?

Sh0wdown commented 5 years ago

Thanks for those addresses, they might help me in the future. Because after making AI-Character changes possible through text files in the upcoming version, maybe I could also do the same for units and buildings.

@Lwndt what crusader version are yours from?

ngc92 commented 5 years ago

@ByBurton That might be why there are still quite a few addresses left. I will look into it later today, maybe I can get it down to one address. Or actually two, one for peasants and one for population.

@Sh0wdown Maybe it would make sense to enable the Wiki for this repo, so we could collect memory addresses and data structures there.

ngc92 commented 5 years ago

For player 1: The number of peasants at the campfire is one of

"Stronghold Crusader.exe"+D5F878
"Stronghold Crusader.exe"+D622F8

The total population is one of

"Stronghold Crusader.exe"+D5F864
"Stronghold Crusader.exe"+D6196C
"Stronghold Crusader.exe"+D61A28
"Stronghold Crusader.exe"+1627086
PodeCaradox commented 5 years ago

Maybe one of you can help me with the static positions from the tiles above Towers. The Positions are stored inside of the exe and for better Graphic mod packs it will be cool to change them. Im not so good to find the bytes for it inside the exe, maybe one of you have more luck with it. I also have created an issue for that: https://github.com/Sh0wdown/UnofficialCrusaderPatch/issues/375

The tiles are above are the following: The static tiles on Top that dissapear if anyone stand on top of the Tower, i can make them invisible from start on, maybe i add this in the Converter Programm: Image124 Image122 Image123

And the other static Images that have the fixed Positions inside Stronghold exe: Image3 Image4 Image2 Image24

If i can change the Positions and maybe the Platforms the soldiers stand on, we can make in future bigger Castle kepps, higher and bigger towers etc..

It will help me alot with my Converter: https://github.com/Gaaammmler/Gm1KonverterCrossPlatform

Maybe i also can help @Sh0wdown with a Unit Editor, if i know the Byte Positions inside the exe and how to change them i write a Porgramm for it or add it to this github Project.

Also if anyone can help metalvoidzz and me, i start to extend the Editor Features, but therefore we need more research for the bytes in the .map files: I linked here metalvoidzz wiki with the .map format he started: https://github.com/Sh0wdown/UnofficialCrusaderPatch/issues/395

GRhin commented 4 years ago

@ngc92 do you have a more detailed list of building indices? along with maybe damage recieved my each unit? I have a large list of data im trying to find in this area, and your lua script has been helpful so far. Also how did you find all these?

ngc92 commented 4 years ago

yes, I do have a more extensive list by now, but currently have no access to a windows machine so I've not been working on it recently. The last thing I was working on was trying to decode the data structures used for buildings. Unfortunately I do not have the newer scripts on my PC right now, I'll try to remember and copy them on the next occasion.

As for getting the unit indices, I tracked the location in the code where the unit type is passed to the spawn function in the unit editor, placed a debugger breakpoint, and then just placed archers in the editor but changed the value at the breakpoint to systematically go through all possible units, and then looked what kind of unit actually spawned. Did the same thing for buildings, there seem to be some unused ones in the game (e.g. a bear cave, if I remember correctly)

@PodeCaradox I would actually prefer the scriped approach to a pre-programmed exe editor. Makes it far easier to do changes (no need to re-patch the exe, you could change after loading) while keeping the changes to the exe to a minimum. Path in a lua interpreter or a call to load lua as a dll, make it call some lua start up script and provide some function to edit memory.

J-T-de commented 4 years ago

@ngc92 Nice, I started collecting Crusader-related data, starting point was the data in this thread, but I also expanded it quite a bit :) If you have more/additional data, feel free to add it.

ngc92 commented 4 years ago

@GRhin This is what I have on building IDs:

BUILDING_NAMES = {}
BUILDING_NAMES[1] = "hovel"
BUILDING_NAMES[2] = "hovel"
BUILDING_NAMES[3] = "woodcutter"
BUILDING_NAMES[4] = "ox tether"
BUILDING_NAMES[5] = "iron mine"
BUILDING_NAMES[6] = "pitch rig"
BUILDING_NAMES[7] = "hunter"
BUILDING_NAMES[8] = "merc post"
BUILDING_NAMES[9] = "barracks"
BUILDING_NAMES[10] = "stockpile"
BUILDING_NAMES[11] = "armory"
BUILDING_NAMES[12] = "fletcher"
BUILDING_NAMES[13] = "blacksmith"
BUILDING_NAMES[14] = "poleturner"
BUILDING_NAMES[15] = "armorer"
BUILDING_NAMES[16] = "tanner"
BUILDING_NAMES[17] = "bakery"
BUILDING_NAMES[18] = "brewery"
BUILDING_NAMES[19] = "granary"
BUILDING_NAMES[20] = "quarry"
BUILDING_NAMES[21] = "quarry stone pile"
BUILDING_NAMES[22] = "inn"
BUILDING_NAMES[23] = "apothecary"
BUILDING_NAMES[24] = "engineer's guild"
BUILDING_NAMES[25] = "tunneler's guild"
BUILDING_NAMES[26] = "market"
BUILDING_NAMES[27] = "well"
BUILDING_NAMES[28] = "smelter"
BUILDING_NAMES[29] = "???"
BUILDING_NAMES[30] = "wheat farm"
BUILDING_NAMES[31] = "hops farm"
BUILDING_NAMES[32] = "orchard"
BUILDING_NAMES[33] = "dairy"
BUILDING_NAMES[34] = "mill"
BUILDING_NAMES[35] = "stables"
BUILDING_NAMES[36] = "chapel"
BUILDING_NAMES[37] = "church"
BUILDING_NAMES[38] = "cathedral"
BUILDING_NAMES[39] = "???"
BUILDING_NAMES[40] = "manor"
BUILDING_NAMES[41] = "keep"
BUILDING_NAMES[42] = "stronghold"
BUILDING_NAMES[43] = "???"   -- has taxes menu
BUILDING_NAMES[44] = "???"  -- has taxes menu
BUILDING_NAMES[45] = "large gate"
BUILDING_NAMES[46] = "small gate"
BUILDING_NAMES[47] = "???"  -- gate?
BUILDING_NAMES[48] = "postern gate"
BUILDING_NAMES[49] = "drawbridge"
BUILDING_NAMES[50] = "tunnel entrance"
BUILDING_NAMES[51] = "training ground"
BUILDING_NAMES[52] = "signpost"
BUILDING_NAMES[53] = "training ground 2"
BUILDING_NAMES[54] = "siege tent (fire ballista)"
BUILDING_NAMES[55] = "camp ground"
BUILDING_NAMES[56] = "archery range"
BUILDING_NAMES[57] = "training ground 3"  -- large post
BUILDING_NAMES[58] = "training ground 4"  -- lance target?
BUILDING_NAMES[59] = "training ground 5"  -- guilds
BUILDING_NAMES[60] = "???"
BUILDING_NAMES[61] = "???"
BUILDING_NAMES[62] = "gallows"
BUILDING_NAMES[63] = "stocks"
BUILDING_NAMES[64] = "witch hoist"
BUILDING_NAMES[65] = "maypole"
BUILDING_NAMES[66] = "gardens"
BUILDING_NAMES[67] = "killing pit"
BUILDING_NAMES[68] = "pitch"
BUILDING_NAMES[69] = "???"
BUILDING_NAMES[70] = "water pot"
BUILDING_NAMES[71] = "???"       -- has taxes
BUILDING_NAMES[72] = "???"       -- has taxes
BUILDING_NAMES[73] = "???"       -- has taxes
BUILDING_NAMES[74] = "watchtower"
BUILDING_NAMES[75] = "perimeter tower"
BUILDING_NAMES[76] = "defence tower"
BUILDING_NAMES[77] = "square tower"
BUILDING_NAMES[78] = "round tower"
BUILDING_NAMES[79] = "round tower ruin"
BUILDING_NAMES[80] = "siege tent (catapult)"
BUILDING_NAMES[81] = "siege tent (trebuchet)"
BUILDING_NAMES[82] = "siege tent (tower)"
BUILDING_NAMES[83] = "siege tent (ram)"
BUILDING_NAMES[84] = "siege tent (shield)"
BUILDING_NAMES[85] = "???"
BUILDING_NAMES[86] = "watchtower ruin"
BUILDING_NAMES[87] = "perimeter tower ruin"
BUILDING_NAMES[88] = "defence tower ruin"
BUILDING_NAMES[89] = "square tower ruin"
BUILDING_NAMES[90] = "???"
BUILDING_NAMES[91] = "cesspit"
BUILDING_NAMES[92] = "stake"
BUILDING_NAMES[93] = "gibbet"
BUILDING_NAMES[94] = "dungeon"
BUILDING_NAMES[95] = "rack"
BUILDING_NAMES[96] = "flogging rack"  -- weird, this does not seem to exist in game
BUILDING_NAMES[97] = "chopping block"
BUILDING_NAMES[98] = "drunken stool"
BUILDING_NAMES[99] = "war dogs"
BUILDING_NAMES[100] = "statue"
BUILDING_NAMES[101] = "shrine"
BUILDING_NAMES[102] = "beehive"
BUILDING_NAMES[103] = "bear"
BUILDING_NAMES[104] = "???"
BUILDING_NAMES[105] = "bear cave"
BUILDING_NAMES[106] = "outpost"
BUILDING_NAMES[107] = "arab outpost"
BUILDING_NAMES[108] = "???"
BUILDING_NAMES[109] = "???"

Hope this helps

GRhin commented 4 years ago

How did you find the unit costs? They seem to be more reliably used than what we were finding. For example changing a unit cost is shown in the barracks as well as the deducted amount. While other times ppl have found unit prices it is just the deducted amount.

LeSpec commented 3 years ago

Maybe this can be added to the wiki? @Krarilotus

UNIT TYPES

ID  Name

1   Peasant
2   Burning Person
3   Woodcutter
4   Fletcher
5   Tunneler
6   Hunter
7   Quarry Mason
8   Quarry Worker
9   Quarry Ox
10  Pitchman
11  Wheat Farmer
12  Hops Farmer
13  Apple Farmer
14  Dairy Farmer
15  Miller
16  Baker
17  Brewer
18  Pole Turner
19  Blacksmith
20  Armorer
21  Tanner
22  Archer
23  Crossbowman
24  Spearman
25  Pikeman
26  Maceman
27  Swordsman
28  Knight
29  Ladderman
30  Engineer
31  Miner (Manufacturer)
32  Miner (Worker)
33  Priest
34  Healer
35  Drunkard
36  Innkeeper
37  Monk
38  // (no unit function like crow and seagull)
39  Catapult
40  Trebuchet
41  Mangonel
42  Trader
43  Horse (Trader)
44  Deer
45  Wolf (Lion)
46  Rabbit
47  Bear (Camel)
48  Crow
49  Seagull
50  Siege Tent
51  Cow
52  Dog (Hunter)
53  Fire Watch
54  Ghost
55  Lord
56  Lady
57  Jester
58  Siege Tower
59  Battering Ram
60  Portable Shield
61  Ballista
62  Chicken
63  Mother
64  Child
65  Juggler
66  Fire Eater
67  War Dog
68  Burning Animal (big)
69  Burning Animal (small)
70  Arabian Bow
71  Slave
72  Slinger
73  Assassin
74  Horse Archer
75  Arabian Swordsman
76  Fire Thrower
77  Fire Ballista
78  empty
79  empty