1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

[TOTPP] Lua Scenario Template

Discussion in 'Civ2 - Scenario League' started by Prof. Garfield, Jul 5, 2020.

  1. Knighttime

    Knighttime Warlord

    Joined:
    Sep 20, 2002
    Messages:
    191
    In Napoleon, we also use 'Tab' as the context-sensitive help key. 'Backspace' along with the number keys '1' through '6' provide various status reports, or allow you to access static help/info screens. (As you noted in regards to 'y', though, number keys have other effects in cheat mode.)

    In the current major project that I'm working on, and hope to release shortly, I chose to use 'Backspace' as the context-sensitive help key, displaying info about the active unit and/or tile. 'Tab' is a "menu" key that brings up a dialog box allowing you to pick from a list of options which are not tied to the active unit. Most of these are status reports of one type or another, but a few allow you to initiate in-game actions that are not unit-specific. I guess I took this approach because I'm familiar with several other apps where 'Tab' is used to access an auxiliary menu, and that seemed the most natural or instinctive choice.

    So overall, I'd say I like having both 'Tab' and 'Backspace' be available for help and supplemental functionality, and I'd be in favor of your proposal of using 'k' and 'u' as munitions keys -- which, if they're providing related functionality, have the added advantage of being close together on the keyboard.
     
    Last edited: Oct 6, 2020
  2. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    3,378
    I suppose this is probably better-placed here than in the Boudicca thread.

    I've made more progress on the Designer Readme. I figured we'd need it, and it also gives me a useful reminder of what events I need to write, because I need to have an example for everything. I have "the high level" stuff done I think, but need specific usage examples still (kind of like I did with the object and parameter settings). I'm not wed to this structure necessarily but I think it makes sense (high level of what things do, then nitty gritty of how to do it with a matching example from the scenario for people to look to/copy/paste).

    @Prof. Garfield if you would be so kind as to review page 9 and specifically the unit defeated/other situations and opine if there is a better way to describe those, I'd appreciate it. I'm sure you had specific usages in mind for the group but I don't fully understand them and could use a small paragraph that is better than mine for each.
     

    Attached Files:

    Dadais likes this.
  3. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,131
    Location:
    Ontario
    As part of the template, I've added in functionality to avoid these situations in my Event Tools.

    Code:
    eventTools.guaranteeUnitActivation(tribe)
    
    This makes sure there will be an active unit for the tribe. This is run afterProduction for each tribe, and if the guaranteed activating unit is destroyed, another one is created. The parameters file sets the location where these guaranteeing units will be created, and what unit type they are. For testing, I chose the North East side of the map, and the arrows unit.

    You probably shouldn't destroy units in the combat resolution function. For the unit you want to lose, set its hitpoints to 0 and then return false. A better example would be a unit that is defeated by a reaction event.

    It is probably worth mentioning that the unitDefeated, unitDeath, and unitDeleted functions exist in part to tie into other events, especially pre-made modules. For example, gen.defeatUnit is used in the reaction module, so putting code in the unitDefeated trigger allows that code to be run if a unit is destroyed in the reaction module. Otherwise, the player would have to "open up" the reaction module if they want stuff to happen when a unit is killed by a reaction.

    Also FYI, I'm thinking it might make sense to add a unitDeathOutsideCombat function. It might make sense to want different events to occur if a unit is killed in combat versus if the unit dies of thirst in the desert, and that isn't straightforward to do with the current setup (though I think it would be possible).

    It might be worth mentioning that the prefix helps when trying to use your text editor's autocomplete, since it filters out the other stuff. In fact, that was my original reason for "recommending" the prefixes in the first place.

    Code:
    ..tostring(loser.type.name)..
    
    FYI, loser.type.name is already a string, so you don't need to use tostring for that. It doesn't hurt anything, but it does make the lines longer.

    Code:
    onSchism–Out of thebox, prevents a civilization from splitting in two when its capital is taken. No modification is necessary unless you want the split to occur.
    
    This is worth double checking, but I think this could be used to trigger an event any time a schism might occur, even if the schism doesn't actually happen.
     
  4. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    3,378
    Can we expand on this function please? It seems to be more limited than in the base game in that it only recognizes "defender" and not "conqueror" as well. Having different events occur depending on who conquers the city is quite important (consider if the Allies reach Berlin before the Russians).

    Code:
    
    function triggerEvents.onCityTaken(city,defender)
        context[getContext()]["onCityTaken"](city,defender)
        universal["onCityTaken"](city,defender)
        legacy.doCityTakenEvents(city,defender)
    
    
     
  5. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,131
    Location:
    Ontario
    I think you would use city.owner to get the conqueror. If you think it would be helpful, I can change the code to provide an 'attacker' argument, and just feed it city.owner in the events.lua file, hiding the details from the end user.
     
  6. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    3,378
    I just tested it and it works - a bit counterintuitive but something that we could explain in the designer guide too. When I think city.owner I'm thinking the defender because it's in the onCityTaken - well, it has to be taken from the owner, right?

    I guess I'd see what others think if they wish to speak up...
     
  7. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,131
    Location:
    Ontario
    I've attached the current progress of the documentation for the text module. Let me know if you think there are any problems with what I have thus far, since I'll probably do more in this style.

    The change isn't that hard to make, and I can't really see any drawbacks to doing it.
     

    Attached Files:

  8. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    3,378
    I don't think there are any issues with it at all - it's quite helpful actually. I'd press on.
     
  9. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    3,378
    I noticed a minor bug in munition settings:

    local function secondaryAttack(generatingUnit)
    return munitions.spawnUnit(generatingUnit,primaryAttackTable,gen.getActivationFunction())
    end
    munitionSettings.secondaryAttack = secondaryAttack

    Should be

    local function secondaryAttack(generatingUnit)
    return munitions.spawnUnit(generatingUnit,secondaryAttackTable,gen.getActivationFunction())
    end
    munitionSettings.secondaryAttack = secondaryAttack

    I fixed it in my copy for Boudicca but if you're keeping a master copy for template distribution it should be fixed as well.
     
  10. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    3,378
    The negotiation settings is not very intuitive for me. What do I need to do to simply change things so no one can negotiate (which I'd assume many scenarios would want)? Is this something that must be done via the legacy engine?


    Code:
    local legacy = require("legacyEventEngine")
    local negotiationSettings = {}
    function negotiationSettings.negotiation(talker,listener)
        legacy.doNegotiationEvents(talker,listener)
        return legacy.canNegotiate(talker,listener)
        --return true
    end
    return negotiationSettings
    
     
  11. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,131
    Location:
    Ontario
    Just return false, instead of returning legacy.canNegotiate(talker,listener). I should probably review that. Either the legacy events aren't working for forbidding diplomacy, or there is a problem with the lua portion.

    My current plan is to take the Boudicca scenario, and remove the Boudicca specific stuff. Otherwise, I'm likely to miss something.
     
  12. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    3,378
    I believe you mentioned that the way you have things situated, the events know to look at various folders for each other. Does this mean that if I had a reason to move a file into, say, the main scenario folder, I could? On another project I'm tinkering with I have multiple rules files which means multiple attack values for units. To get attack bonus settings working properly, I need to have an attackBonusSettings for each rules file (as I believe I need to define the attack rating within that file).

    Would it hurt anything to put the attackBonusSettings in the main scenario folder so that I can easily write a batch file to swap them? I am not sure how to write the file to search the folder to swap them/don't want to break something.
     
  13. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,131
    Location:
    Ontario
    Yes, you could lua files into the main scenario folder, or any of LuaCore, LuaParameterFiles, LuaRulesEvents, LuaTriggerEvents. You can't put them into any subfolders, unless you specify that folder in your use of the require function. The Folders are mostly for organization. The only stuff where location matters are the universal and context trigger files. Those must stay where they are (though I suppose you could move the entire folders if you wanted to for some reason).
     
  14. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    3,378
    In the case below with the delayed action, is "turn" seeking a specific turn, or a number of turns after the trigger? I'm hoping it's the latter as I think it would allow design to become more fluid. You might have a trigger that you want to grant a specific thing "5 turns from the trigger" but that could mean "turn 10, 15, 20, 183 etc."

    Is this what this aims to do or is that incorrect?

    Code:
    --  If you want an event to take place at some point further into the future,
    --  in the onTurn event phase for that turn, use the following function
    --
    --  delayedAction.doInFuture(delayKey,argTable,turn)
    --
    --      delayKey    is the string that you've associated with the function you
    --                  wish to delay
    --
    --      argTable    is the table that should be provided as an argument
    --
    --      turn        is the turn you wish the event to take place
    
     
  15. Dadais

    Dadais Warlord

    Joined:
    Oct 20, 2010
    Messages:
    230
    Location:
    France
    It shall be any of these two on choice if I understand well the description.

    Either the turn numbered x, then allocate x.
    Either x turn after the actual turn, then allocate civ.getTurn() + x

    ;)
     
    Last edited: Dec 11, 2020
  16. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,131
    Location:
    Ontario
    Dadais likes this.
  17. Dadais

    Dadais Warlord

    Joined:
    Oct 20, 2010
    Messages:
    230
    Location:
    France
    Trying to stick to that.
    I also used "i" for improvement object. I saw you (all) used a function to return by name comparing a string each time. Is there a purpose for this ?
     
  18. Prof. Garfield

    Prof. Garfield Deity Supporter

    Joined:
    Mar 6, 2004
    Messages:
    3,131
    Location:
    Ontario
    I'm not sure what you mean. Can you post a relevant portion of code that shows what you are asking about?
     
  19. Dadais

    Dadais Warlord

    Joined:
    Oct 20, 2010
    Messages:
    230
    Location:
    France
    Well, in Napoleon for exemple, the improvements are looked after by a function findImprovementByName(string), which then look each time in all 40 improvements for such a named improvement to return it.
    Didn't put my head in recent codes howether, like OTR.

    I wondered if this system using strings as reference had an advantage I may miss (nooby with lua after all) in compare with an early allocation like made with units, tribes and cities ?
     
  20. JPetroski

    JPetroski Deity

    Joined:
    Jan 24, 2011
    Messages:
    3,378
    I like the integer based system because it allows players to tweak city names, for example, if they'd like. In OTR, you can rename your cities whatever you wish. If we used a string, you could only rename cities to something that is also referenced, or the event wouldn't work.

    Also, if you mess around with multiple rules files, I'd argue that integers allow more flexibility.
     

Share This Page