Majesty Gold HD

Majesty Gold HD

Customize Majesty!
Create and upload new Quests and Mods for Majesty HD!
Alfryd 23 Jul, 2016 @ 5:18am
GPL code- some general newb questions
Hi there- I finally got around to making a small custom quest, and after peering through the SDK and making some educated guesses about gaps in the tutorial, I had some questions.


(1) How much of the existing GPL functions (that I'd find under the SDK/OriginalQuests/etc.) would need to be left intact to avoid breaking the existing quests? Which functions are (or not) common to both vanilla and MajX?

(2) How does the game evaluate what functions are modified/overwritten by a given mod or quest-bytecode?

(3) Is there any particular restriction on which functions need to go in which files? e.g, if I took all the functionality related to Healers, the Temple to Agrela, all their spells and sovereign-spells and bunged it into one or two central files, would the compiler care? Could I factor out the lairs and quest-buildings into separate directories?

(4) How does the game evaluate what buildings are available to the player? Is it just scanning all the DAT files? How would dependencies and upgrade-chains be specified (or can they)?

(5) Finally, I seem to have missed the GPL that defines the various original/expansion quest-behaviours themselves? Where can I dig that out?


(Maybe CyberloreDev can field some of these, but amantalado suggested I post this here for the sake of general reference. Thanks in advance.)
< >
Showing 1-15 of 25 comments
amantalado 1 23 Jul, 2016 @ 2:37pm 
1) Technically, you wouldn't need to leave any intact. If a function belonging to a quest ends up breaking the quest when you modify it, then chances are that the function just needs a bit of fine-tuning to allow for quest parameters to flow through it. The difference in functions for vanilla and MajX are mostly discovered on a function-by-function basis. Some are exactly the same, others have slight differences, while a few are heavily changed from one to the other. You'd have to just compare/contrast the original and MajX function of whatever one you're looking at before making a modification to suit both, or just one.

2) The game will ALWAYS take the modified functions you put in and override the original game's functions.

3) The compiler won't care. I slapped all of my functions into a single Master File, and all that happens is that compiling it takes longer than normal and takes up more space. Leaving them in separate, manageable files is more for organization and compartmentalization so you don't have to open a massive text file each time you want to mod a specific thing.

4) No idea. That's hard-coded currently, and can't really do anything to the base game's structures other than make them unbuildable. All you can do is add new buildings and take away old ones without any conditions applied to enable them. No upgrade chains either, yet.

5) Those are in the Rules folder. SDK\OriginalQuests\GPL(x)\Rules
Alfryd 23 Jul, 2016 @ 3:05pm 
Thanks for the tips!

Now I know where the quests are defined I should be able to do some basic regression testing, but it might not hurt if I started compiling a list of the Maj/MajX function differences for the sake of future wanderers.

I'm guessing I could look at the Wrath of Krolm for examples of how structures/lairs are defined, but are there any extra gotchas when it comes to player buildings?
amantalado 1 23 Jul, 2016 @ 3:26pm 
Originally posted by Alfryd:
Thanks for the tips!

Now I know where the quests are defined I should be able to do some basic regression testing, but it might not hurt if I started compiling a list of the Maj/MajX function differences for the sake of future wanderers.

I'm guessing I could look at the Wrath of Krolm for examples of how structures/lairs are defined, but are there any extra gotchas when it comes to player buildings?

I have every function in the GPLMx folder compiled into a single text file for easy comparison whenever I pull up a function from the Original for comparison. If you want it, I can upload and post a link to it.

As for player buildings, it all really comes down to your approach and what you plan on doing with them. You might not run into any of the problems I have because you are focused in a different area than me. The main thing to take into account is whenever a building/unit you made or modified is pre-placed on the map and manipulated by the code. If you have certain aspects of your buildings modified or changed through something like a birth script, then pre-placement can end up glitching some things out. In such a case, when it comes to Birth functions especially, include 'If' statements to check that the properties you're intending to manipulate on a building or unit has actually taken effect before passing the rest of the argument through.
Alfryd 23 Jul, 2016 @ 4:11pm 
Ah, I see. So birth-scripts don't apply automatically for pre-placed structures... I guess that makes sense.

One other problem, actually- how do I inspect printouts made with DebugOut? They don't seem to appear in the external debug console or within the in-game GPL debugger, so far as I can tell? Have I missed something?

EDIT: And yes, I'd appreciate getting a look at that function listing.
Last edited by Alfryd; 23 Jul, 2016 @ 4:12pm
amantalado 1 23 Jul, 2016 @ 5:23pm 
Originally posted by Alfryd:
Ah, I see. So birth-scripts don't apply automatically for pre-placed structures... I guess that makes sense.

One other problem, actually- how do I inspect printouts made with DebugOut? They don't seem to appear in the external debug console or within the in-game GPL debugger, so far as I can tell? Have I missed something?

EDIT: And yes, I'd appreciate getting a look at that function listing.

I don't know, never figured out how to get the debugger to work.

Here's the link to all the scripts from MajX: Master Script MX[www.filedropper.com]
Alfryd 24 Jul, 2016 @ 5:08am 
Cheers.
Originally posted by amantalado:
I don't know, never figured out how to get the debugger to work.

Whoa whoa whoa. Is shift-underscore or shift-vbar not working for you? Being able to inspect printouts sounds like a fairly important tool. @CyberloreDev- please let me know if I or amantalado missed something here.

Meanwhile I'm gonna stick my work on github[github.com], if anyone wants to take a peek. (Working on some changes to dodge/parry mechanics at the moment, and maybe address some other basic balance problems. I'm gonna leave it as a sandbox-type quest for now, until I'm confident about releasing a general mod.)
Last edited by Alfryd; 24 Jul, 2016 @ 11:28am
Alfryd 24 Jul, 2016 @ 3:29pm 
Oh, one other thing- I looked up the definitions for most of the sovereign spells under Tasks/Subtasks/, IIRC, but couldn't find any explicit function definition for Illusory Hero (although I think the unit type *is* defined somewhere...) Is that another hard-coded thing we can't really tamper with for now?
amantalado 1 24 Jul, 2016 @ 7:19pm 
Looks like it. You can certainly mess with it to a certain degree by modifying the Illusionary Hero's Birth Script. It's in the Hero_Births.gpl file, with that you can change the effect of the sovereign spell to whatever you desire.
Cyberlore Dev  [developer] 1 24 Jul, 2016 @ 8:18pm 
1) If you are making a Quest, then you can change anything you like. A quest is an island unto itself and its code will be loaded only when it is played, so no need to worry about compatibility with anything. If you are making a mod, it is more tricky, you have to be sure to not change anything that would prevent another quest from running, completing, etc. Of course, a user can just turn off your mod if there are issues, so no big deal.

2) Code is loaded first to last, so the last that is loaded wins. This is done on the function level, so if function Foo is defined in one mod, or base game file, the last function definition of Foo to load, is the one that is used.

3) No restrictions on where things are located, the compiler will compile everything into the destination bytecode file.

4) Buildings are defined in the dat files, but can be turned off by the Quest startup code. Units can be disabled too, look for $disableunittype in the epic_quest_scripts.gpl for examples.

5) All the startup scripts for the base game quests are in epic_quest_scripts.gpl. For the expansion, they are in Quests_1.gpl, Quests_2.gpl and Quests_3.gpl

Getting the GPL debugger working is a great help to doing anything with GPL code, I would advocate trying to make it work again. Make sure you have <UseGPLDebugger>1</UseGPLDebugger> set in your MajXPrefs file in your My Games/MajestyHD folder. I'd also advise that you run the game in windowed mode, so you can see the exception popups easier if you make a runtime GPL error, and also turn on the debug window with <UseDebugWindow>1</UseDebugWindow> in the MajXPrefs file or -debugoutwindow on the command line. This will create a separate window that will show logging output. Logging output will also go to Logs\err.log or Logs\gpl.log in your My Games/MajestyHD/Logs folder.
Alfryd 25 Jul, 2016 @ 1:16am 
Thanks a bunch!

Might be my imagination, but I thought I had UseDebugWindow toggled and I still wasn't seeing DebugOut calls show up... I'll check the logs as well.
Last edited by Alfryd; 25 Jul, 2016 @ 1:17am
Alfryd 29 Jul, 2016 @ 3:10pm 
Yeah, I've tried running in windowed mode with UseDebugWindow toggled and checked Logs/err.log and Logs/gpl/log as well- I'm not seeing any trace of the debugout calls I made. Is there some error in the syntax I'm using?

//----------------------------------------------------------------------------- // Main entry point for combat interactions: function make_attack(agent acting, agent target) declare integer hitResult, expGiven; begin if ($notvalid(target)) return; if ($notvalid_attacker(acting)) return; $hit_reaction(acting, target); hitResult = $hit_check(acting, target); expGiven = $exp_value(acting, target); $debugout(acting's "title"); $debugout(" performed attack, result: "); $debugout(hitResult); if (hitResult == 1) begin $deal_damage(acting, target); end if (hitResult == 2) begin end if (hitResult == 3) begin end $attack_end(acting, expGiven); end
Alfryd 29 Jul, 2016 @ 4:24pm 
Also, it should be possible to override the various spell-effector definitions in M_Overlays.xml, right? I was hoping to make the various healing spells into gradual-regeneration buffs, but the callback function I specified seems to be completely ignored.

EDIT: Well, that's not quite true. It seems to be called exactly once, but calling createeffector to extend the duration has no effect. Ideally, I'd like the callback to be triggered at regular intervals (say, once per second,) until completion-criteria are met. Any tips?
Last edited by Alfryd; 29 Jul, 2016 @ 4:32pm
amantalado 1 29 Jul, 2016 @ 9:14pm 
If you're telling the effector to create itself again after it ends to simulate a regeneration interval, it won't work. The effector is considered on until every action in the ending function is executed, which means calling it back again as part of it's end function won't do anything. You'd have to make it loop through two effectors calling each other in instead of just one that perpetuates itself.

If that's not what you meant, then I don't know. It's difficult to figure out the steps you are taking from words alone.
Alfryd 30 Jul, 2016 @ 3:03am 
I pushed the latest version of the code to the repo, so you should be able to view it there[github.com]. Snippets below...

function Agrela_Heal_Effect(agent affects) // player cast spell - from temple to agrela declare begin if ($isdead(affects)) return; $player_heal(affects, 10); $createeffector(affects, "agrela_healing_effector", 1000); end function agrela_heal_end(agent affects) declare integer health, maxHP; begin $player_heal(affects, 1); health = $GetAttribute(affects, #ATTRIB_HP ); maxHP = $GetAttribute(affects, #ATTRIB_MAXHP); if (health < maxHP) begin $createeffector(affects, "agrela_healing_effector", 1000); end end
<Description type="Unit" subType="Overlay" ID="HRA1" Name="agrela_healing_effector" Description="Agrela healing"> <Engine version="1"> <Info value="Directionless"/> <Info value="DontBlock"/> <Menu value="11"/> <ImageIDBase value="HRA1"/> <Script type="0" cProc="0" GPLFunction="agrela_heal_end"/> <DefaultSound value="Healing"/> </Engine> <Game version="1"> <DialogID value="0"/> <StackPriority value="0"/> <Flags value="TransparentToMouse"/> </Game> </Description>

...So what you described was what I was aiming for, yeah. Is there any documentation on what the various script parameters in the overlay definition mean? e.g, could I use type="2" to have the GPFunction called every hundred frames? The tandem-effectors solution just seems a bit awkward.
Last edited by Alfryd; 30 Jul, 2016 @ 3:16am
amantalado 1 30 Jul, 2016 @ 12:06pm 
I haven't experimented with the various parameters whose functions aren't clearly explained in their name. You shouldn't need an effector to set up interval healing, you can do it with the $NewThread function to execute a looping thread that can mimic the healing you want. It's what I use for the majority of my effect over time scripts.
< >
Showing 1-15 of 25 comments
Per page: 1530 50