Ship Spawning
-
Yeah, me too. How is that even possible? Maybe I’m just not knowledgeable enough in the subject matter but I wasn’t aware that you could even pull something so detailed (especially with regard to names of things) from just assembly level de-compilation.
-
Defining those structures was relatively trivial, due to exported constructors. Doing the points above will take a bit more effort, which I’ll not do (not for a while, anyway, by which time I’ll have forgotten). I expect point two can be solved by set_current_directive, so I suppose you want IDirectiveInfo and the remaining Ops?
-
I’m not asking you to do them at all, you’re a busy man with a lot on your plate
What I wondered is whether you could give some insight on how to do what you do. A tutorial if you want, just some tips otherwise. I’d like to stop having to ask you or w0d all the time, but I’ve never gleaned much from disassemblies
-
Well, if you want to give it a go, here’s an example using DirectiveFollowOp.
* Exported function Common.??0DirectiveFollowOp@AI@pub@@QAE@XZ | =1<===== 062DAF30 8BC1 mov eax, ecx 062DAF32 33C9 xor ecx, ecx 062DAF34 C7400404000000 mov dword[eax+04], 00000004 062DAF3B 894808 mov [eax+08], ecx 062DAF3E C7001CE13906 mov dword[eax], Common.??_7DirectiveFollowOp@AI@pub@@6B@ 062DAF44 89480C mov [eax+0C], ecx 062DAF47 C7401000001643 mov dword[eax+10], 43160000 ; 150 062DAF4E 894814 mov [eax+14], ecx 062DAF51 894818 mov [eax+18], ecx 062DAF54 89481C mov [eax+1C], ecx 062DAF57 C740200000C843 mov dword[eax+20], 43C80000 ; 400 062DAF5E C3 ret ```I have a separate program to demangle names, which gives us the namespace and constructor. [eax] is the virtual function table, [eax+04] & [eax+08] are from BaseOp. Looking at Follow in the mission files and where it reads it in content.dll (6F27400), +0C would be the nickname, but I still don't know what the other values are, apart from being float (probably maximum distance, x,y,z offset and something else). So assuming that, we can say:
namespace pub
{
namespace AI
{
enum OP_TYPE { FollowOp = 4 }; // and the others, of courseclass DirectiveFollowOp : public BaseOp // inheritance based on observation { public: DirectiveFollowOp()/* : BaseOp( FollowOp )*/; // some more functions here, should be in the CoreSDK virtual bool validate(); UINT leader; // 0 float max_distance; // 150 Vector ofs; // 0, 0, 0; copy constructor indicates Vector float unknown; // 400 };
}
} -
Very nice, that should help a lot!
Can I know what program(s)/steps you use to get the output you’ve shown? I think I read you use Ollydbg to disassemble the DLLs, but how do you get the values like 150 or 400? From the INIs, from a debug process?
-
Excuse me while I go hang myself for being so blind. -_-
-
The listing was generated by a customised PEReaDeR, which I’ve attached, since I should do a bit more on it before releasing the patch (I haven’t updated my first patches with Freddy’s better code). Use perdr -b common.dll >common.lst for the listing shown. I’ve also included the demangler:
[[url=http://adoxa.110mb.com/tde/]tde] c:/Projects/undec ??0DirectiveFollowOp@AI@pub@@QAE@XZ
public: __thiscall pub::AI::DirectiveFollowOp::DirectiveFollowOp(void) -
FriendlyFire wrote:
Excuse me while I go hang myself for being so blind. -_-Never do that.
Go blow away a criminal who escapes justice.
You will feel a lot better afterwards!
And then 8 years later they will let you out and you can do another one!
-
class IMPORT DirectiveGotoOp : public BaseOp { public: DirectiveGotoOp(class DirectiveGotoOp const &); DirectiveGotoOp(void); virtual bool validate(void); public: int x00; int iGotoType; // 1 = Vec, 0 = Ship Vector vPos; // pos int iTargetID; // id Vector vSpline1; // ? Vector vSpline2; // ? Vector vSpline3; // ? Vector vSpline4; // ? float fRange; float fThrust; bool x58; // in INIs, don't know what it does bool x59; // Always true? short iFlag; // 0 = goto, 1 = goto_cruise, 256 = goto_no_cruise int x5C; float x60; // 200 float x64; // 500 int x68; int x6C; };
-
Remove x00.
iGotoType also has 2 = spline, 3 = undefined (I guess, that’s what the constructor does).
short iFlag; is actually bool goto_cruise; bool goto_no_cruise; (“goto” is ignored).
x59 has no apparent reference in content (certainly not where it reads the Goto lines), maybe it gets used in common. -
I gathered as much for the types (I just hadn’t tested it). For the iFlag, I kinda guessed they’d be bools. It seems that goto_cruise overrides goto_no_cruise, too, if both are set to true inadvertently.
As for x00, I had to add that because of a hack I did to BaseOp. I can tell you it works perfectly right now so the definitions are proper
-
Hello everyone,
I’m very interested in this topic, and I follow it since its beginning. Thanks to your great work, I slowly understand how to make NPC’s spawning.
As Wodk4 said, It would be nice to give Waypoints to NPC. Unfortunately, I didn’t reach this objective.
Here the first thing I tried to do :
pub::AI::DirectiveGotoOp testOP; testOP.iGotoType = 1; testOP.vPos.x = -14507; testOP.vPos.y = 124; testOP.vPos.z = 11492; testOP.iFlag = 256; pub::AI::SubmitState(iSpaceObjID, (pub::AI::BaseOp*)&testOP);
but this does’nt work. (This would be too simple, you can laugh at me)
so I tried to use the Personality.cpp given by Adoxa, but unfortunately, I don’t know how to use it. I tried to place it into server.h, in the AI namespace, but I have some errors.
Can you help me to find what’s wrong ?
(No code required, but at least a little clue)Thanks a lot,
Kid -
pub::AI::DirectiveGotoOp testOP; ```Is wrong. It's waiting for a pointer (notice the *). Use
pub::AI::DirectiveGotoOp* go = new pub::AI::DirectiveGotoOp();
And remember to replace all the "." by "->". You also need to define fRange and fThrust.
-
Well, I tried to do as you said, but the spawning ship really doesn’t want to move. I think I haven’t the skill yet to understand it well, and don’t want to annoy you more than that. I don’t know what fThrust & fRange stand for, even playing with values.
(The weird thing, is that in the code quoted by Wodk4, it’s not a pointer which is used in the submit state line).Here’s my current code, according that iSpaceObjID represent a ship we’ve just created. The waypoint is approximatively 500 m away from the spawn point.
pub::AI::DirectiveGotoOp* testOP = new pub::AI::DirectiveGotoOp(); testOP->iGotoType = 1; testOP->vPos.x = -14507; testOP->vPos.y = 124; testOP->vPos.z = 11492; testOP->iFlag = 1; testOP->fRange = 1; testOP->fThrust = 1; pub::AI::SubmitState(iSpaceObjID, (pub::AI::BaseOp*)&testOP);
Really, if you don’t have the time / motivation to help me, no problem, I 'll try to go on by myself.
A huge Thanks anyway
-
fThrust is the speed at which the ship goes. -1 is the default value in the game and means full speed.
fRange is how far from the destination the ship has to go.
Did you define a pilot and a state graph?
-
You changed testOP to a pointer, but didn’t change it in the call.
pub::AI::SubmitState(iSpaceObjID, testOP); ```Although depending on just how DirectiveGotoOp has been defined, you might still need to cast it (it should have been derived, so there should be no need).
-
The older headers don’t have the inheritance. You’d need to add it to the definition of all Op classes.
-
I have set all the personality settings, but I either only get a standing ship (setting state_graph to -1) or an instant server crash.
int iStateGraph = pub::StateGraph::get_state_graph("FIGHTER", pub::StateGraph::TYPE_STANDARD); IStateGraph const *sg = pub::StateGraph::get_state_graph_internal(iStateGraph); pub::AI::SetPersonalityParams pp; pp.state_graph=(int) sg; pp.personality=p; pp.state_id=true; pub::AI::SubmitState(iSpaceObjID, (pub::AI::BaseOp*)&pp);
It doesn’t matter whether I set state_id to true or false or use iStateGraph for the state_graph variable.
Any hints?
-
Ok, I solved it by setting the stategraph afterwards using the BehaviorManager. But as long as you don’t know much about Freelancers internal objects you wont get that far ^^ Maybe there is an easier way?