Modify message

Subject:
Message icon:

Attach:
(Clear Attachment)
(more attachments)
Restrictions: 4 per post, maximum total size 1024KB, maximum individual size 1024KB
Verification:
Type the letters shown in the picture
Listen to the letters / Request another image

Type the letters shown in the picture:
Type ot the full word: TUR**:
Finish the word: Turok 2: Seeds of ****:
Finish the word: Turok Dinosaur ******:

shortcuts: hit alt+s to submit/post or alt+p to preview


Topic Summary

Posted by: Smoke39
« 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
Posted by: BehemothProgrammer
« 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.
Posted by: Smoke39
« 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).
Posted by: BehemothProgrammer
« 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.
Posted by: Smoke39
« 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
Posted by: BehemothProgrammer
« 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.
Posted by: Smoke39
« 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.
Posted by: BehemothProgrammer
« on: March 09, 2019, 02:02:25 PM »

That works because QuakeSource is a shared class. https://www.angelcode.com/angelscript/sdk/docs/manual/doc_script_shared.html

Quote
Shared entities have a restriction in that they cannot access non-shared entities because the non-shared entities are exclusive to the script module in which they were compiled.

And that's not going to work when trying to get non shared classes from the game default scripts. And also it says there that you can share funcdefs which is wrong, or the angelscript version used in the game is really old. So casting to a non shared class compiled from another module will always return null. The only way to do custom things with non shared scripts is with that helper function that's able to call a function on an actor to the game module with 4 floats that can do whatever.

In this game there are 2 modules for scripting, I'll call them the game module and the map module. https://www.angelcode.com/angelscript/sdk/docs/manual/doc_module.html
Posted by: Smoke39
« on: March 09, 2019, 03:47:09 AM »

Shit, you can actually get an actor's script object from a level script?  I tried doing that while making Cliffside Outpost, and as I recall I was getting cast errors, so I thought the game and level script contexts were just so distinct that they each had their own distinct copies of classes or something.  Just did a quick test with a QuakeSource from a level script, though, and I was able to call SetupShake() and mess with its member variables, so apparently I was doing something wrong before.  Really good to know that's possible after all.

Given that, I'm not sure what the purpose of using InteractActorsAtPosition() is?  Why not just get a handle to the dummy actor's script object and call the function directly?

Thanks for the notes.  I'll parse through them eventually, but just skimming through them I'm noting some nice little nuggets. :)
Posted by: BehemothProgrammer
« on: March 09, 2019, 01:24:54 AM »

Nice work listing all the attacks for all the enemies. That was something annoying I never wanted to do, but needed to lol. You pretty much got everything listed that's awesome.

Your mentioning InteractActorsAtPosition and I just wanted to show a helper function I used for calling functions from the map module to an actor in the game module, that uses InteractActorsAtPosition. This function will spawn a special actor type at the players position and set it to solid so InteractActorsAtPosition will call it. You only want the function to be called on the actor once instead of for every solid actor in range so you need to do a condition check for that actor type at the start of your function.

Code: [Select]
//------------------------------------------------------------------------------------------------------------------------
// Useful to call custom functions from the map script module to the game script module.
// Otherwise just use the ScriptObject's ScriptObject() function to get a handle to it.
//
// Required:
// Function header: void funcName(kActor @actor, const float arg1, const float arg2, const float arg3, const float arg4)
// Function body condition check: if (actor.Type() != BP_AT_FUNCTIONCALL) return;
//------------------------------------------------------------------------------------------------------------------------
void CallFunc(kActor@ actor, const kStr &in funcName, const float arg1 = 0.0f, const float arg2 = 0.0f, const float arg3 = 0.0f, const float arg4 = 0.0f)
{
kActor@ playerActor = Player.Actor().CastToActor();
kActor@ dummy = Spawn(BP_AT_FUNCTIONCALL, playerActor.Origin(), 0.0f, playerActor.SectorIndex());
dummy.Flags() |= AF_SOLID;
actor.InteractActorsAtPosition(playerActor.Origin(), funcName, arg1, arg2, arg3, arg4);
dummy.Remove();
}

and going the other way from game to map module is easy with the Game.CallDelayedMapScript function.

Here's the last of my random stuff I found out when making my last map that I don't think you have in the guide, hope it helps.
https://pastebin.com/raw/fExJrV1j
Posted by: Smoke39
« on: March 08, 2019, 03:16:36 AM »

Clearing out a backlog of stuff I accumulated while working on my first map:

Figured out which params are which with kActor::SpawnParams().

The levels section has been massively expanded.  In addition to a bunch of handy reference info, of particular note are a couple of quirks with triggers:
1. enemy Target TID can only trigger other actors on death, not level scripts
2. event sectors can only trigger level scripts if there are no actors with a matching TID
Posted by: DoomMarine23
« on: March 07, 2019, 03:56:57 PM »

Glad to see you've continued with this. When I get the time, maybe this weekend or next week, I am gonna look into documenting a few functions as well.
Posted by: Smoke39
« on: March 07, 2019, 03:25:56 AM »

After a fair bit of experimentation, I think I've reverse-engineered the details of how kActor::MeleeObject() works.  I also documented kActor::InteractActorsAtPosition(), which can, for example, be used to implement custom alternatives to MeleeObject().
Posted by: Smoke39
« on: September 03, 2018, 06:30:20 PM »

I update stuff occasionally as I refine my understanding: https://github.com/Smoke39/turok/commits/master
Posted by: Smoke39
« on: February 05, 2018, 12:34:16 AM »

Added some info to kCModel and kActor::CanSee(), based on some experiments with raycasting.  The new CModel info is from a post Kaiser made on steam a long time ago, but I tried to rephrase the function descriptions to be a little clearer now that I've finally done some actual testing.
SimplePortal 2.3.6 © 2008-2014, SimplePortal