Author Topic: Smoke's Modding Guide  (Read 10846 times)

Offline Smoke39

  • Endtrail
  • ****
  • Posts: 216
  • T:REP 686
    • View Profile
Re: Smoke's Modding Guide
« Reply #50 on: March 09, 2019, 04:54:25 PM »
Okay, I think I understand.  I think with Cliffside Outpost I was trying to mess with movers, which aren't shared, so that would explain it.

So to answer my own question, if you wanted to get a handle to the dummy actor's script object, it'd have to be declared shared.  But if it's shared, then it wouldn't be able to interact with any non-shared entities.  So you use InteractActorsAtPosition() to interact with non-shared entities in the game module from the level module.

This may be naiive, but then why not just redeclare everything shared?  You wouldn't be able to access global variables, but those could be changed to member variables in a shared class.

Offline BehemothProgrammer

  • Endtrail
  • ****
  • Posts: 225
  • T:REP 801
    • View Profile
Re: Smoke's Modding Guide
« Reply #51 on: March 10, 2019, 05:36:21 PM »
So to answer my own question, if you wanted to get a handle to the dummy actor's script object, it'd have to be declared shared.  But if it's shared, then it wouldn't be able to interact with any non-shared entities.  So you use InteractActorsAtPosition() to interact with non-shared entities in the game module from the level module.
Right you got it.

Quote
This may be naiive, but then why not just redeclare everything shared?  You wouldn't be able to access global variables, but those could be changed to member variables in a shared class.
You could, but I don't think you really want to modify all of the game scripts for that and not be able to use global variables, funcdefs, and whatever other types it doesn't support. I wouldn't do that. You shouldn't need to communicate with the ScriptObjects directly very much or not at all from the map scripts. In the rare event you want to do more you can use that helper function, but you might want to ask yourself if what your trying to do could be done in the actors script itself.

For instance if your trying to change the water height in a special way. Then maybe you want to make an actor that handles that and changes the water height when it gets triggered some way. In the map editor you can setup the actor with all the data it needs to know what to do with those SpawnParams, and also if you don't need them for collision, you can use: Radius,Height, WallHeight, and StepHeight. And the 3 spawn flags, are all accessible. Then when the actor is triggered it'll change the water how you want it. You should try to break down all the special things you want to do in your map to generalized actors that can handle everything you want to do with a simple OnActivate call from an event trigger.

It's one of the things I did in my last map was making all those kinds of actors that I needed. An actor that spawns items in any way I want, A counter actor that increases a number and triggers an actor/script when it reaches a certain value, An FxSpawner, An EventLink for handling trigger conditions to actors/scripts, HUD Messages, Playing sounds, modifying anything about a sector/area, a collision trigger area that triggers actor/scripts when you touch it, etc... Then you start to see that you really don't even have to do any scripting in the map, but in some situations you might and that's where it can come in handy.
Turok 2 Co-Op Mod

QTurok | Turok: Mountain of the Sun | WolfenTurok 3D | and more...

Offline Smoke39

  • Endtrail
  • ****
  • Posts: 216
  • T:REP 686
    • View Profile
Re: Smoke's Modding Guide
« Reply #52 on: March 11, 2019, 04:34:55 AM »
I know I can make new actors with custom functionality.  I was trying to avoid actor type ID collisions with Turok+, especially if I reorganize it in the future.  I guess that's kinda silly, considering there are over 4 billion possible actor type IDs, which leaves plenty of room for massive buffers between ranges of values.  I'll probably try to be smarter with my future maps. :b

Offline BehemothProgrammer

  • Endtrail
  • ****
  • Posts: 225
  • T:REP 801
    • View Profile
Re: Smoke's Modding Guide
« Reply #53 on: March 11, 2019, 05:28:18 PM »
Yeah lol you don't have to worry about that. What's weird about this game is that actors with the same type like -1, can still be spawned by it's name, and you can still access it's correct Definition. But the editor uses the type instead of the name, so if you're only using actors to spawn at runtime you can set all their types to -1. But yeah I usually just reserve 1000 ids for my mod and I know I'll never go beyond that.
Turok 2 Co-Op Mod

QTurok | Turok: Mountain of the Sun | WolfenTurok 3D | and more...

Offline Smoke39

  • Endtrail
  • ****
  • Posts: 216
  • T:REP 686
    • View Profile
Re: Smoke's Modding Guide
« Reply #54 on: March 12, 2019, 06:10:29 PM »
Are you sure there are float versions of AddItem() and Select() for kSelectionListFloat?  I'm getting warnings about implicit type conversion when I try to pass floats to AddItem(), and when I print the result of Select() I'm not getting any decimal places.  I'm also not seeing float versions of those functions in the executable (though I'm just searching for strings in a text editor).

Offline BehemothProgrammer

  • Endtrail
  • ****
  • Posts: 225
  • T:REP 801
    • View Profile
Re: Smoke's Modding Guide
« Reply #55 on: March 12, 2019, 08:17:40 PM »
I just checked it again, and yes it looks like kSelectionListFloat is exactly the same as kSelectionListInt. :o And int& Select(const bool = false) has a bool parameter.

Some more info on map scripts. $restart remaps to
Code: [Select]
void Game.CallDelayedMapScript(const int scriptID, kActor @instigator, const float delay)
where scriptID is taken from the last $script <id> value used in the script before $restart. instigator is placed in the instigator actor arg and the delay is 0. So it's calling itself and will execute itself on the next script execution cycle (not immediately). You can do this same thing and call CallDelayedMapScript(const kStr &in funcName, kActor @instigator, const float delay) for your custom map functions in order to loop them.
Turok 2 Co-Op Mod

QTurok | Turok: Mountain of the Sun | WolfenTurok 3D | and more...

Offline Smoke39

  • Endtrail
  • ****
  • Posts: 216
  • T:REP 686
    • View Profile
Re: Smoke's Modding Guide
« Reply #56 on: March 12, 2019, 11:06:46 PM »
I just checked it again, and yes it looks like kSelectionListFloat is exactly the same as kSelectionListInt. :o And int& Select(const bool = false) has a bool parameter.

Thanks for the confirmation.  The bool was added and the return value changed to a reference in 2.0.  Anecdotally, passing true seems to get results slightly closer to the expected values, but heck if I know what it's actually doing.

Some more info on map scripts. $restart remaps to
Code: [Select]
void Game.CallDelayedMapScript(const int scriptID, kActor @instigator, const float delay)
where scriptID is taken from the last $script <id> value used in the script before $restart. instigator is placed in the instigator actor arg and the delay is 0. So it's calling itself and will execute itself on the next script execution cycle (not immediately). You can do this same thing and call CallDelayedMapScript(const kStr &in funcName, kActor @instigator, const float delay) for your custom map functions in order to loop them.

Did some quick testing 'cause I was curious about how $restart would work in non-numbered level scripts, and inside functions called from other level scripts.  The impression I'm getting is that by "last $script used before $restart," you're talking about the actual topography of the file, not the execution order.

So for example if you had something like this:
Code: [Select]
$script 1
{
}

void Blah()
{
$restart;
}

$script 2
{
Blah();
}

and then called Game.CallDelayedMapScript( 2, Player.Actor(), 0 ), you'd get $script 2 -> Blah() -> $script 1

Offline BehemothProgrammer

  • Endtrail
  • ****
  • Posts: 225
  • T:REP 801
    • View Profile
Re: Smoke's Modding Guide
« Reply #57 on: March 13, 2019, 04:54:56 PM »
yup that's what will happen. Just have to declare a kActor@ named instigator before $restart in that example.
Turok 2 Co-Op Mod

QTurok | Turok: Mountain of the Sun | WolfenTurok 3D | and more...

Offline BehemothProgrammer

  • Endtrail
  • ****
  • Posts: 225
  • T:REP 801
    • View Profile
Re: Smoke's Modding Guide
« Reply #58 on: March 13, 2019, 06:51:06 PM »
More stuff.

AAF_EVENTSOUND - (must be paired with AAF_EVENT) arg2(in editor) is to be set to the soundID defined in defs/fileLookup.txt. When the player enters the area that sound will play. Be careful though, the event in arg4 will also be executed.

-----World-----
void FloodFillAreaFlags(  int sector, uint flags, bool bSet ) - DO NOT USE!!! (Use FloodMatchingAreaFlags instead) This can only turn OFF area flags. If you attempt to turn ON any flag while that flag is already ON for that sector/area, the game will crash.

void ChangeAreaFlag( int areaID, uint flags, bool bSet ) - DO NOT USE!!! (Use FloodMatchingAreaFlags instead) Only certain flags work correctly when set. The full list of my tests is:
Code: [Select]
AAF_WATER = 1 << 0 //works, partially. No shallow water sound effects play.
AAF_BLOCK = 1 << 1 //does NOT work
AAF_TOGGLE = 1 << 2 //
AAF_CLIFF = 1 << 3 //does NOT work
AAF_CLIMB = 1 << 4 //does NOT work
AAF_ONESIDED = 1 << 5 //(Bridge) does NOT work
AAF_CEILING = 1 << 6 //does NOT work
AAF_CRAWL = 1 << 7 //works
AAF_ENTERCRAWL = 1 << 8 //works
AAF_HIDDEN = 1 << 9 //works
AAF_ENTERED = 1 << 10 //
AAF_SECRET = 1 << 11, //works
AAF_RESTRICTED = 1 << 12 //works
AAF_SLOPETEST = 1 << 13 //does NOT work
AAF_DEATHPIT = 1 << 14 //works
AAF_MAPPED = 1 << 15 //does NOT work
AAF_EVENT = 1 << 16 //works
AAF_REPEATABLE = 1 << 17 //
AAF_TELEPORT = 1 << 18 //works
AAF_DAMAGE = 1 << 19 //works
AAF_DRAWSKY = 1 << 20 //works
AAF_TELEPORTAIR = 1 << 21 //works
AAF_LAVA = 1 << 22 //works
AAF_EVENTSOUND = 1 << 23 //works
AAF_ANTIGRAVITY = 1 << 24 //works
AAF_LADDER = 1 << 25 //works
AAF_CHECKPOINT = 1 << 26 //works
AAF_SAVEGAME = 1 << 27 //works
AAF_WARPRETURN = 1 << 28 //
AAF_SHALLOWWATER = 1 << 29 //works
AAF_DRAWSUN = 1 << 30 //works
AAF_STOREWARPRETURN = 1 << 31 //


void FloodMatchingAreaFlags( int sector, uint flags, bool bSet )
void FloodFillAreaFlags( kVec3& loc, uint flags, bool bSet )

both work for all flags so use these instead.

« Last Edit: March 13, 2019, 06:58:01 PM by BehemothProgrammer »
Turok 2 Co-Op Mod

QTurok | Turok: Mountain of the Sun | WolfenTurok 3D | and more...

Offline Smoke39

  • Endtrail
  • ****
  • Posts: 216
  • T:REP 686
    • View Profile
Re: Smoke's Modding Guide
« Reply #59 on: March 14, 2019, 03:06:22 AM »
Did some more testing and found some quirks with $script 0.  Made a new level scripts section, and updated kGame::CallDelayedMapScript().  I'm not going out of my way to verbosely spell out all the preprocessor stuff with examples 'n' such since I think it's kind of academic, but I think I've got all the basic info there.

Thanks for the area flags stuff.  Those function issues are pretty big; I'll probably try to take care of them soon.