Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
The DLL Project
#31
I thought of something that might make things simpler concerning how to get code called by the game.

The initial idea was to release a list of code addresses and descriptions of those.
The problem is, the data you want to work with will lie in certain registers or somewhere in the stack frame and it would require you to use assembly in order to access them.
That's something I believe should be simplified, and what I thought of are callback functions.

Once the game reaches a specific code address, that would raise an event which gets all the necessary data from the registers/stack and passes it to your callback function as arguments.
These callback functions you would have to define at the game start (which is no problem).

You'd still have to edit the INI with code addresses, because you should remove all the "events" you don't use (they'd still be raised and the DLL would be called... to no avail -> possible slowdown with multiple DLLs).

So, the advantage of this is sane names instead of code addresses, and C variables instead of registers and stack frames.

Any ideas to improve this idea?
[Image: jsfml.png]
Reply
#32
Wait, so rather than individual lines, thic would return blocks of code, and we would have to pick out the right ones?
Renegade - I pity the fools who moved on to Generals modding.
Guest - Because they can already do all of this?
Renegade - No, because they sold their soul to the devil instead of having faith and waiting for the messiah.
Reply
#33
No. This is actually easing up your work - PD would define a function format for each specific event, and you would be responsible for following that format in your functions. E.g.
Code:
// type definition in PD's headers
typedef void BuildingEnteredCallback(cObject *, cInfantry *);

// function in your source, note the format has to match
void BuildingEntered_tryFreeCapture(cBuilding *target, cInfantry *infiltrator) {
if(target->regurgitates) {
  cInfantry::spawn(infiltrator->ID, infiltrator->owningHouse, target->exitCoord); // sample code to spawn a clone of the entering infantry belonging to the infiltrator's house, basically making the building capture free
}
}
As a replacement for asm blocks, this is very welcome.
However, I would use a "yrpp_dllName.dll" + "yrpp_dllName.ini" instead of a global ini file. Because you just know lusers are going to delete a DLL without unregistering its entries sooner or later, although your code should be able to handle that gracefully in either case. There's also the issue of multiple DLLs hooking up to the same address, which is ew, not to mention the Windows standard INI parsing routine doesn't distinguish between multiple lines with the same address as a key.

Worth playing: 1 | 2 | 3
Reply
#34
On the callbacks, exactly.

On the rest, first off, every DLL will have its own ini. Smile
That has been planned exactly like that. Your DLL's INI should just not include "events" it does not use, because that would add unnecessary breakpoints, and every breakpoint will result in a DLL call.

The "issue of multiple DLLs hooking up to the same address" is no problem at all, not even in the same INI.
I'm not using Windows' INI parsing, I wrote my own. The Debugger is made so it accepts multiple breakpoints on one instruction.
I really do believe I've thought of most possible cases, but that we'll only see in its application... Wink
[Image: jsfml.png]
Reply
#35
What if ...
  • a DLL needs per-object variables like cBuilding::timesThisHasBeenCaptured ?
  • I want a crate that makes every single unit on the map cloaked for two minutes, and, naturally, not lose the actually cloakable units' cloak when uncloaking everything else afterwards? I imagine the callback on MyTimerExpired will need to iterate the units and reload their Cloakable status from the INI, meaning certain INI changes will work mid-game and potentially desync.
  • I want a new AI Script Action/Trigger Event/Action ?
    • And two developers reuse the same Action number?
  • I want to lift the built-in array length limits like ScriptType/TaskForce length?
  • multiple DLLs hook up to one address, and ...
    • the first one sets a return address, does that block the second, third, etc. DLL from receiving the event?
    • two of them set different return addresses?
    • the first one alters a data structure which the second one was going to access? Different results depending on the DLL call order. E.g., callback on UnitAttacked(cObject *target, cObject *attacker, cWeapon *weapon) , the first DLL does weapon->damage += some_value_dependant_on_the_attacker's_stats (hm, there should be other ways without altering the weapon for later shots...) , and the second replenishes the attacker's hitpoints by weapon->damage points. Switch the DLL order, wham, different replenishment.

Worth playing: 1 | 2 | 3
Reply
#36
Yeah, you named quite a few possible contradictions there.

If one DLL sets a return address, the breakpoint won't be called anymore, I think I've stated that sometime already, in my last post I forgot that.
The question is when does somebody actually need to set a return address?

Anyway, many things you're talking about I'm actually aware of, the return address, same action or other values, critical property changes. Of course not every DLL will be compatible to every other DLL,
like mods aren't always compatible to each other (UT2004 has exactly the same problems!).

Therefore it's pretty important for people to know what a DLL changes, if it is designed to be compatible to others, which mines for example are to be.


To the first points:
DCoder Wrote:What if a DLL needs per-object variables like cBuilding::timesThisHasBeenCaptured ?
If one DLL accesses that very variable, it's stored in the game, not in that one DLL.
Once you changed it, it's changed for the other DLLs as well, unless it's declared in that DLL.

A problem is of course that one DLL can not access another DLL, unless that other DLL has export functions designed to communicate with others (I plan on doing this with mine).

DCoder Wrote:What if I want a crate that makes every single unit on the map cloaked for two minutes, and, naturally, not lose the actually cloakable units' cloak when uncloaking everything else afterwards? I imagine the callback on MyTimerExpired will need to iterate the units and reload their Cloakable status from the INI, meaning certain INI changes will work mid-game and potentially desync.
Every Techno (Vehicles, Infantry, Aircraft, Buildings) is linked to a TechnoType, which holds the "Cloakable" tag, thus is doesn't have to be reloaded. Also the veteran/elite abilities are accessible via TechnoTypes.

Most ingame classes have a corresponding type class.
Infantry (ingame) - InfantryType (INI)
Anim - AnimType
Terrain - TerrainType
The list goes on long.

The type classes can be referred to as templates for the ingame classes.

DCoder Wrote:What if I want a new AI Script Action/Trigger Event/Action ? [And two developers reuse the same Action number?]
In this case, I'll probably define callback function which return a boolean value, as in "handled" or "not handled".
If handled, it will set the return address(*), if not, it won't, and it's a possible next DLL's turn.

(*) Yes, this means that if two DLLs use the same value, only the first one loaded (at the moment this goes alphabetically) will receive it.
This is why I will most definitely release lists about such values I use.

DCoder Wrote:What if I want to lift the built-in array length limits like ScriptType/TaskForce length?
You might have realized already that not everything will be doable using just the callbacks.
For instance, I'm not planning to add callbacks for every single use of a property (like the scripttype array), which means you'd have to create your own in such a case.

Coding-wise, you'd do this by
a) actually adding it to the ScriptTypeClass, which would require you to increase the amount of memory allocated for the ScriptTypeClasses before being constructed, or
b) keep a map (or similar) which assigns each ScriptTypeClass pointer to a custom structure which holds the additional information, while the assignment should be a reaction on the construction event (likewise when the object gets destructed, you drop the assignment).

I used to stick to method (a) in the RP times, but for the DLLs I'm most likely going to use method (b).
In both cases you'll have to modify every single usage of the modified properties and make it point to your newly allocated structure.
This is the type of case that will require you to set a return address, ie your DLL will be in danger to be compatible to others (concerning ScriptTypes).


DLLs truly make adding easier than modifying existing stuff, quite the opposite of exe hacking. Whether that's good or bad, we'll see. Confused
[Image: jsfml.png]
Reply
#37
Yeah I know, lack of updates bleh blah.
I've taken a "little" excurse and made a UT2004 map, which took me like 2 weeks...
http://img111.imageshack.us/img111/7214/...713vd1.jpg < little picture from it. Smile

Anyway, there's also some YR++ progress.
Little but important thingies like always, but today I've also made it possible to easily add new CommandClasses.

What are CommandClasses?
Well, go to the options, Keyboard, and there you have several categories listing a bunch of commands.
These sorts can now easily be added, which means you can call them whatever you like, put them in your own category, have them bint to a key ingame and code their functionality!
This should be a lot of fun and will be most useful if you want to test stuff.
[Image: jsfml.png]
Reply
#38
Nice.

Oh, and where to download the UT map?
Ever wondered what the hell is going on?
Believe me friend you're not the only one.
--Lysdexia

Check out Launch Base for RA2/YR - http://marshall.strategy-x.com
Also home to the Purple Alert mod, 1.002 UMP, and the YR Playlist Manager.
Reply
#39
I finally have enough class definitions so that I can work on other useful things if I need a change from this stupid copy and pasting (which is essential on the other hand)...

Not sure how long it used to take me to register a new SuperWeapon Type in assembly, anyway, now it's gonna take you 5 minutes.
You can add a custom SuperWeapon type using but two callback functions, one for parsing the Type name loaded from the INI, the other for parsing the value when the weapon is launched:

Code:
#define SWTYPE_TEST 99

int SWTypeParse(const char* pSWType)
{
    if(_strcmpi(pSWType,"Test")==0)
        return SWTYPE_TEST;
    else return -1;
}

bool SWLaunched(SuperClass* pThis,CellStruct* pMapCoords)
{
    SuperWeaponTypeClass* pType=pThis->get_Type();
    if(pType->get_Type()==SWTYPE_TEST)
    {
        CellClass* pCell=MapClass::GetCellAt(pMapCoords);

        CoordStruct Crd;
        pCell->GetCoords(&Crd);

        new AnimClass(AnimTypeClass::Find("ELECTRO"),Crd);

        return true;
    }
    return false;
}

This is a simple SuperWeapon that can be used using the type "Test" and it will play the ELECTRO anim where you fire it.
The two functions are callback functions, this is the way they can be "activated" in DLLMain or whatever you use:
Code:
SuperWeaponTypeClassCallback::Callback_ParseSWType = SWTypeParse;
SuperClassCallback::Callback_SuperWeaponLaunched = SWLaunched;

I won't explain it deeply now, if you know callback functions, you'll see how this works, if not, just let someone explain or wait for some documentation, hehe.
Work goes on now. x)
[Image: jsfml.png]
Reply
#40
Tell me if I'm wrong (which I probably am, I know nothing about this) but would:
SuperWeaponTypeClassCallback::Callback_ParseSWType = SWTypeParse;
tell the game to search for the section with the relevant name and the [SuperWeaponTypes] for a listing with the relevant name.

and

SuperClassCallback::Callback_SuperWeaponLaunched = SWLaunched;
tell the game to search for stuff like AI targeting values ect.
Reply
#41
Quote:Not sure how long it used to take me to register a new SuperWeapon Type in assembly, anyway, now it's gonna take you 5 minutes.

I like what I hear. Does that mean you can add loads of featers in a faster time? New sides, deploy logic and so on.....

(damn forgot my pass)
Reply
#42
It is more like that: When you buy a brand new Porsche, you can choose color, extra equipment etc. - That's RockPatch.
With YR++ you can build a car on your own, you've got already all the parts (engine, wheels, etc.) but you must put them together. This actually requires quite a lot of knowledge how to build a car, but easily let's you build interesting variations (-> see "Pimp my Ride").
Any questions?
[Image: osen2o7mpmm4jg1fs0.jpg]
Reply
#43
LEGO! Big Grin 2

Worth playing: 1 | 2 | 3
Reply
#44
I was wondering if this is going to be a recon-error-free patch?
I am so f*cking sick of NPatch recons.
Reply
#45
pd said somewhere that he can't guarantee it because he didn't spend much time on the multiplayer control. I guess this will come after the most important points of YR++ are finished...
[Image: osen2o7mpmm4jg1fs0.jpg]
Reply




Users browsing this thread: 1 Guest(s)