[1.011]Mount&Blade Script Enhancer 0.3

Users who are viewing this thread

Thaess

Regular
Hello, I'd like to present you my Mount&Blade Script Enhancer for Mount&Blade 1.011. I'm not sure if there are still mods being created for 1.011, but I'm doing this just for fun and satisfaction. Why I'm sharing it? Maybe someone's still creating mod for 1.011 and this would be useful for him.

Version 0.3 said:
- Fixed string operations not using string tags correctly ( {reg0} {s0} etc.)
- Added operation is_first_person, set_first_person, agent_get_animation,agent_get_animation_progress, scene_prop_slot_eq, scene_prop_slot_ge, scene_prop_slot_gt, scene_prop_slot_le, scene_prop_slot_lt, scene_prop_slot_add, scene_prop_slot_sub, troop_set_name, troop_set_name_plural,
- Ability to customize agent's sounds by new operation agent_set_sound.

Changelog
Version 0.1 said:
- New string operations: str_cmp, str_join, str_len, str_reverse, str_substr, str_to_int, str_swap, str_lower, str_upper, str_split, str_is_alpha, str_is_digit, str_get_ascii, str_store_join, str_store_reverse, str_store_substring, str_store_lower, str_store_upper, str_starts_with, str_ends_with.
- is_mbse_active operation
- New trigger: ti_on_agent_hit
Version 0.2 said:
- Added optional parameter "case insensitive" to str_cmp, str_starts_with, str_ends_with
- Added operations: agent_get_item_slot, agent_set_item_slot, agent_get_used_weapon_slot,is_cheat_mode_active, set_cheat_mode, scene_prop_set_slot, scene_prop_get_slot, str_is_empty, store_trigger_param, is_edit_mode_active
- Added item flag itp_lance that allows to couch polearm while on horse (polearms without this flag can not be couched)
- Enchanced trigger ti_on_agent_hit
Trigger Param 1: id of agent that received damage
Trigger Param 2: id of agent that delivered damage
Trigger Param 3: hit damage
Trigger Param 4: hit bone
Trigger Param 5: agent dealer's weapon
Trigger Result: Greater or equal 0 will change the damage
- Fixed bug with storing 32bit values instead of 64.

1. Unpack the zip archive into your Mount&Blade directory.
2. Move header_operations_addon.py and header_triggers_addon.py to your Module System directory.
3. Add the content of header_operations_addon.py at the at the end of header_operations.py.
4. Add the content of header_triggers_addon.py at the at the end of header_triggers.py.
5. Add the content of header_common_addon.py at the at the end of header_common.py.
6. Add the content of header_items_addon.py at the at the end of header_items.py.

Everything you need to run this is "Mount&Blade 1.011 Enhanced Edition". What is it? It's silently released M&B 1.011 version which is not packed with Themida, so it's possible to create such a tool.

Mount&Blade 1.011 Enhanced Edition
Download MBSE
 
Pretty cool. Woah, didn't expect for this one-like come alive.
 
Haha, great, now all you need to do is develop this enhancer to the point when good old M&B+MBSE will wipe Warband out of the market. :wink:
 
Uh, is it permitted in the EULA to redistribute the main executable like this?

I mean... where did this "special edition" come from, and why isn't it going to have issues with the DRM?  Sorry, I know that's probably going to cause some hackles to rise, but, eh... it might be wise to make sure this is kosher before handing out an executable that can run the game for free and such.
 
xenoargh said:
Uh, is it permitted in the EULA to redistribute the main executable like this?

I mean... where did this "special edition" come from, and why isn't it going to have issues with the DRM?  Sorry, I know that's probably going to cause some hackles to rise, but, eh... it might be wise to make sure this is kosher before handing out an executable that can run the game for free and such.
:lol: You didn't know about the super secret enhanced edition? Look at URL of the download link.

Nice job Thaess, if you fall within the lines of the WBSE this would be great.
 
xenoargh said:
Uh, is it permitted in the EULA to redistribute the main executable like this?
Who said a word about redistributing M&B? Mount&Blade is still available from Taleworlds, so you only need to distribute MBSE. :smile:
 
This is unexpected to say the less.  :eek:

If you're seeking for some new additions... I particularly need these operations for speeding up the Star Wars Conquest map editing process. They are priceless for developing a copy-paste scene prop functionality through mission templates...

Code:
edit_mode_in_edit_objects_mode = 4600 #(edit_mode_in_edit_objects_mode), #Fails if the game is not in edit objects mode
edit_mode_get_num_selected_prop_instances = 4601 #(edit_mode_get_num_selected_prop_instances, <destination>), #Stores the number of selected prop instances into <destination>
edit_mode_get_selected_prop_instance = 4602 #(edit_mode_get_selected_prop_instance, <destination>, <index>), #Stores the <index>th selected prop instance into instance no into <destination>
edit_mode_select_prop_instance = 4603 #(edit_mode_select_prop_instance, <prop_instance_no>), #Stores the <1>th selected prop instance into instance no into <prop_instance_no>
edit_mode_deselect_prop_instance = 4604 #(edit_mode_deselect_prop_instance, <prop_instance_no>), #Stores the <1>th selected prop instance into instance no into <prop_instance_no>
edit_mode_get_highlighted_prop_instance = 4605 #(edit_mode_get_highlighted_prop_instance, <destination>), #Stores the highlighted prop instance into <destination>
edit_mode_set_highlighted_prop_instance = 4606 #(edit_mode_set_highlighted_prop_instance, [<prop_instance_no>]), #Stores the <1>th selected prop instance into instance no into [<prop_instance_no>]

With a bunch of the more basic ones I'm served and grateful... (multi-selection is optional)
Thank you in advance.



@xeno, Lav & Co:

They simply did a polished ninja release on 2009 and served it for a time frame, then, for an unknown reason they taked it down until we acknowledged the differences.

My mate Ar - Adunakhor and me investigated about this and later we re-uploaded the file to the repo.
Taleworlds grabbed it and is currently shipping it again from the official servers with the "enhanced version", that is how I originaly named the file on my local copy.
 
Update!
Version 0.2 said:
- Added optional parameter "case insensitive" to str_cmp, str_starts_with, str_ends_with
- Added operations: agent_get_item_slot, agent_set_item_slot, agent_get_used_weapon_slot,is_cheat_mode_active, set_cheat_mode, scene_prop_set_slot, scene_prop_get_slot, str_is_empty, store_trigger_param, is_edit_mode_active
- Added item flag itp_lance that allows to couch polearm while on horse (polearms without this flag can not be couched)
- Enchanced trigger ti_on_agent_hit
Trigger Param 1: id of agent that received damage
Trigger Param 2: id of agent that delivered damage
Trigger Param 3: hit damage
Trigger Param 4: hit bone
Trigger Param 5: agent dealer's weapon
Trigger Result: Greater or equal 0 will change the damage
- Fixed bug with storing 32bit values instead of 64.

And two little demos:
http://www.youtube.com/watch?v=s07bzasO_XE
http://www.youtube.com/watch?v=nmHRjTXnkRM
 
Hello, this is all very useful! And interesting! Thank you!!!

So let me get this straight.

Do I understand correctly that...

The game itself, at least in its "enhanced version", is able to process (at runtime) a wider set of operations (from the module txt files) than the normal Module System is able to produce (at module compilation time). For example, it understands more operations than the ones listed in "header_operations.py", more triggers than the one listed in "header_triggers.py", more flags for item than the ones listed in "header_items.py" etc.
So you are providing an enhancement of the module system which gives a more complete access to the operations actually supported at runtime, (by means of headers add-ons plus modifications of the txt-producing python code)... Is that so?

If so, many questions arise, mainly:
how did you find you about these operations/triggers/etc and their details?
and,
how many of these extra-bits-of-language-understood-by-the-game are left?


Apologies if any of that sounds dumb.
 
mtarini said:
Hello, this is all very useful! And interesting! Thank you!!!

So let me get this straight.

Do I understand correctly that...

The game itself, at least in its "enhanced version", is able to process a wider set of operations (from the module txt files) than the normal Module System is able to produce. For example, it understands more operations than the ones listed in "header_operations.py", more triggers than the one listed in "header_triggers.py", etc.
So you are providing an enhancement of the module system which gives a more complete access to the operations actually supported at runtime, (by means of headers add-ons plus modifications of the txt-producing python code)... Is that so?

Hey Marco! :smile:

Those script enhancers are just two independent projects, a loader, that launches the game suspended, takes over the memory or unprotects if needed, injects/ patches the code so it calls to
Code:
LoadLibrary
, and a DLL runtime.

The library hooks the documented function addresses, that you've previously reversed or disassembled from the PE file. Redirecting the flux to your own crafted assembler code and later returning back to the same point. (Although you can also do some bindings in a higher level language)

In this case, as it has been previously said, the game uses a switch case for itinerating between all the opcode functions. These enhancers makes the program to jump at the end of the structure to the DLL, where they've added some more functions that coexists with the original implementation. Of course, all of this is much more complex, but basically this is as far as I know.

You'll find more info and resources in places like GameDeception.
Although they're not commonly used for these kind of tasks.


Code:
- Loader (independent program)-->

CreateProcess <mount&blade.exe> (using CREATE_SUSPENDED)
WaitForInputIdle
WriteProcessMemory <whatever>
ResumeThread
...
<game runs as normal and launcher closes>

- DLL Init (game memory)-->

Your hook routines
<rest of functions, patches and enhancements that are called in determinate parts of the game
 redirecting to the new code>

- - - - - - - - - - - -
The enhanced version is needed because of the exe protector (in this case Oreans Themida) scrambles, compresses and usually obfuscates the code (the program decompresses itself in memory changing the address space after doing some checks against debuggers and so).

Making the reverse and later patching more cumbersome, challenging and changing.
 
Thanks, very useful info.

Even better... that means that any command can be in principle be added.

I think these two would really, really be useful:
agent_get_animation     # returns id of current animation of an agent
agent_get_animation_progress
(currently there are there are the "set" versions of these two commands)

and also:
troop_set_name (the opposite of str_store_troop_name).
(currently you can do that for parties, but not for troops)
 
Wow, will it?
This feels like Xmases used to feel.

Im cannot resist adding these to my wishlist (if they are possible--they might not be).

Code:
(agent_set_orientation, <pos1>),
  same semantics as agent_set_position, but sets its orientation instead (for some reason, agent_set_position neglects orientation... which is very bad and impossible to work around).

Code:
(dead_agent_set_speed, <pos1>, <pos2>),
this would set the speed of a dead agent for rag-dolling purposes. Speed is determined as difference between two positions. I know it might be a mess to do. It would be sweeter if you got to pick the bone receiving the impulse, but no need

Code:
(is_first_person),
  fails if 3rd person view is set

Code:
(default_cam_get_position, <pos_no>),
Code:
(default_cam_get_aperture, <dest>),
  same as "mission camera" operations, but they return the default camera, the one that the game uses when not in manual mode (currently there is no way to ask for default camera position unless camera mode is set to manual, that is, unless you set the camera position yourself)

Code:
(current_cam_get_position, <pos_no>),
Code:
(current_cam_get_aparture, <dest>),
  same as "mission camera" operations, but they return current camera position, whatever it is.

-------------------------------

How difficult is to inject code? The wishlist would be so long for added features...

For example, in first person view, the camera is not where it should be, that is, between the eyes of the controlled agent, but in the origin of the "head" bone. This looks wrong, even in vanilla. It would be an instruction to add that (a translation added, at the very last). It would be even sweeter if one could customize eye position (with respect to head bone) in any way.
 
mtarini, now that you're at it, could you clarify the M&B operations controlling camera movement? What they take as input and what they do? I never had to deal with these yet. :sad:
 
mtarini said:
Code:
(agent_set_orientation, <pos1>),
You mean setting rotation? I will take a look.

Code:
(dead_agent_set_speed, <pos1>, <pos2>),
Code:
(default_cam_get_position, <pos_no>),
Code:
(default_cam_get_aperture, <dest>),
Code:
(current_cam_get_position, <pos_no>),
Code:
(current_cam_get_aparture, <dest>),
Maybe in future... Actually I know practically nothing about physics or mission camera, and for now I don't have very much time to find out some about it.

Code:
(is_first_person),
The upcoming version contains it already.

EDIT:
@Swyter, I'm currently working at it. Just give me some time :razz:.
 
Thaess, mate. Can you throw me up an operation for querying the currently selected scene prop instance in the scene editor?.
That's all what I need. I'll do an open source scene editing framework with that. (Copy / Paste / Clone / Swap) Y'know.

That is top priority. As I'm still learning to do all this stuff by myself and hence not ready for doing my own injector.
Maybe in a couple of months, or so. :smile:
 
@Lav

Lav said:
mtarini, now that you're at it, could you clarify the M&B operations controlling camera movement? What they take as input and what they do? I never had to deal with these yet. :sad:

Apologies for hijacking this thread to answer this, but quickly:

It's all quite straightforward.

Background: camera and positions

Here "Camera" stands for all the view parameters (position+direction, and aperture).
It describes the virtual camera capturing the scene.

Positions (i.e. position+direction) are dealt with in the usual M&B way: variables in the scripting languages store only numbers (floats or, more commonly, integers). Positions can only be stored in a special set of "position registers", named form "pos0" ... to some "pos63". Remember each "position" holds both a xyz position and an orientation, that is a facing, encoded with three Euler angles.

There are several commands to deal with these positions (they start with "pos_"): they move them around, set or get x,y,z coordinates, get or set rotations, copy them to another position register, etc. You can also get/set positions of agents, of parties on the map, etc.


Camera modes:

In any given moment during a battle (or a mission, in general), the camera can be in one of two states:
- default mode (you know, 1st person or 3rd person, depending on the player choice, following main hero)
OR
- manual mode (when you the modder override the default position with a position of your choice).

Detail: the manual camera has always a position/direction/aperture, I think, even when it is not used because you are in default mode.

Code:
(mission_cam_set_mode, a, b ), 
switches between default (a = 0) and manual (a = 1)
If you go from default to manual, the optional b parameters specifies how long must it take (in secs) to "fly" to the current manual-camera position. Use b=0 (the default) to mean instant.

Then there are a bunch of parameters to define the position+orientation, and aperture of the manual camera, or read them back.
they are like:
Code:
mission_cam_[i][ get | set | animate_to ][/i] _ [i][ position | aperture][/i]

e.g.
Code:
mission_cam_set_position
  or 
Code:
mission_cam_animate_to_aperture
.

They do what you'd expect: set commands assigns them, get commands queries them, and animate them causes the manual camera to fly there in a given time (there is also an extra parameter choosing how to go there: constant speed or starting slow and accelerating)

Remember than none of the "set" or "animate" commands will have any visible effect if you are in default mode.

Hope this helps.


Back to my request above:

That request stems from the fact that (and this takes as back to the thread topic...)
I currently don't have any command to capture the default camera position.

Capturing the "manual" camera position doesn't help.

I could get the current player agent and ask for his "position" (agent_get_position), or even his "look" position (agent_get_look_position), but none of them returns the real default camera position (even if they are close enough). First of all, they return a position which is at ground 0, between the feet of the agent. I could move that by constant values to get to the eyes, but unfortunately I cannot account for the current animation, which moves the head.




@Thaess

Thaess said:
mtarini said:
Code:
(agent_set_orientation, <pos1>),
You mean setting rotation? I will take a look.

Yes, you are right, that would be a name more consistent with the rest of the language.

You would not believe the amounts of half-working workarounds that the absence of that command caused us in TLD.


Thaess said:
Code:
(dead_agent_set_speed, <pos1>, <pos2>),
Code:
(default_cam_get_position, <pos_no>),
Code:
(default_cam_get_aperture, <dest>),
Code:
(current_cam_get_position, <pos_no>),
Code:
(current_cam_get_aparture, <dest>),
Maybe in future... Actually I know practically nothing about physics or mission camera, and for now I don't have very much time to find out some about it.

Ok, no prob. These would be useful, but my first requests
agent_get_animation,  agent_get_animation_progress, and troop_set_name
are higher priority (and they look easier to do)


Thaess said:
Code:
(is_first_person),
The upcoming version contains it already.

Great!


 
Apologies for double posting, but I would like, if possible, to propose a command which would do wonders for our Mod:

 
Code:
( agent_set_victory_cry, <agent_id>, <sound_id> )

which sets the victory cry for the given agent. (in alternative, or in addition, it could be done per troop instead of per agent).

Currently, that depends on the "skin" (the race, as we know) of the troop which generated that agent.

In TLD, we would need that to avoid "wasting" otherwise identical races just to make them shout different victory cries (e.g. orcs from mordor and from isengard hailing different masters, and many different cases). But in general I can see several other potential uses, like victory cries which depend on the contest not just the shouter (e.g. to ear troops shout "death to swadians" in vanilla or whatever).

(I don't think that this can reliably be substituted by scripting using simple
Code:
agent_set_sound
commands, because re-scripting over the hardwired mechanisms which triggers cheer-sounds would be probably heavy and quirky.



I've would also have a similar request for setting "death"/"hit" or  "gallop" sounds for individual horse agents (oh, if only we could make horses sound like horses but wargs sound like wargs in our TLD mod, in a less quirky way!)
 
Back
Top Bottom