Page 1 of 2 12 LastLast
Results 1 to 30 of 33

Thread: Newbie scripting question [LevyScript]

  1. #1

    Default Newbie scripting question [LevyScript]

    I'm a fairly experienced coder whose just recently gotten into MT2TW modding and the first thing I've decided to try and cook up is a Levy Script (sortof a counterpoint to Klink's garrison script. The main roadblock I'm running into is a lack of understanding of how to get at certain info thats necessary for making the script even operate.

    I've provided the pseudocode below in the hoped of getting some feedback as to which functions and grammar I'll need to accomplish the following;

    ;::::Start Test Levy Script;::::
    declare_counter muster_isbuilt
    set_counter muster_isbuilt 0
    ;;;;;[[Pseudo Code in question]]
    ;::::Check if Muster_call [building] is built in a particular settlement [London]
    ;::::if yes [muster_isbuilt == 1], get the settlement's population [int]
    ;:::: get settlement's tech level (wall) [int]
    ;:::: get info on settlement building types [bool + int]
    ;:::: get info on settlement governor [bool + int]
    ;:::: ??Get info on neighboring settlements?? [bool + int]
    ;:::: Spawn units based on this info

    ;::::Example Usage:
    ;::::[if Building A exists in London]
    ;:::: [settlement_pop = Settlement_pop London]
    ;:::: [if Building B exists in London]
    ;:::: [B_exists = 1]
    ;:::: [if Governor Z has trait1]
    ;:::: [Governor_has_trait1 = 1]
    ;:::: [if neighboring region [Sherwood] belongs to player1]
    ;:::: [neighboring_pop = Settlement_pop Sherwood]
    ;::::[London_muster_score = settlement_pop/1000 + (B_exists * 100) + (Governor_has_trait1 * 100) + (neighboring_pop/2000)
    ;::::[if London_muster_score > 0 && < 5000]
    ;:::: [create_unit London, Peasants, num 4, exp 0, arm 0, wep 0]
    ;::::
    ;::::

    If anyone has any ideas as to which functions I cna use to get even a bit of this done, as well as some syntax examples, I'd be eternally greatful.

  2. #2
    Harbinger of... saliva Member alpaca's Avatar
    Join Date
    Aug 2003
    Location
    Germany
    Posts
    2,767

    Default Re: Newbie scripting question [LevyScript]

    Haha yes, you'll be frustrated by M2 scripting before long
    Basically, something like you want to do is much, much more difficult than you'd expect with M2 scripts. Some of the problems:
    - no real variables
    - no counter-to-counter or counter-to-exposed comparison (only counter-to-constant)
    - no functions, only commands and conditions
    - conditions are boolean only
    - most conditions have a game object as trigger requirements and thus only work in monitor_event
    - no maths (well except for adding and subtracting and even then, only counter + constant)

    Doing what you want to do requires a lot of creative thinking and compromises. I'm working on something similar and it's really hard to factor in a lot of the game state because you can't use variables.
    You can design a few workarounds by using while loops, gigantic if-lists and such, but it's really not pretty.

  3. #3

    Default Re: Newbie scripting question [LevyScript]

    Well, I don't mind doing a lengthy workaround, I'm mainly concerned with whether its possible to get the info I want. For instance, Klink' script does something like this;

    declare_ counter Dongola_lev
    set_counter Dongola_lev 1
    monitor_event SettlementTurnStart SettlementName Dongola
    and SettlementBuildingExists = wooden_wall
    set_counter Dongola_lev 2
    end_monitor

    Basically, where can I find a list of conditions that I can use in monitor events like SettlementBuildingExists?

    I'm not afraid of fat if lists. :)

  4. #4

    Default Re: Newbie scripting question [LevyScript]

    you need to refer to the Docudemon files v 1.2

    https://forums.totalwar.org/vb/showthread.php?t=83119

  5. #5

    Default Re: Newbie scripting question [LevyScript]

    Check the Mod Chat forum, and download Caliban's Docudemon files v1.2.

    The main problem in regards to your script is that you need to check for all your conditionals all at once. In other words, you can't be like:

    if building_A exists
    ...if building_B exists
    ......do something
    ...end_if
    ...if building_C exists
    ......do something else
    ...end_if
    end_if

    The reason for that is that almost all conditionals consume outside data, data supplied by EVENTS. If you read the events document in docudemons, you will see. Events, such as SettlementTurnStart, supply all of the content that the conditionals then consume and use. There is no:

    if building_A exists in settlement ABC. It's only

    if building_A exists.

    How is the script going to know which settlement? Only by using this conditional in conjunction with an event that supplies the settlement name.

    That's the basic framework that you have to work around. It's far from a full-fledged scripting language. Now given this limitation, you can still create some rather sophisticated programs. And also let me point out that a few conditionals don't need to be supplied with an event's data, they are entirely stand-alone. In the conditions file, you will see those conditions as ones having the I_ prefix, e.g. I_SettlementExists. Ideally, all of conditionals should have I_ formats, (poke Caliban), as that would untie our hands in unbelievable ways. But for now, we have to be satisfied with those that already exist. Hopefully I still haven't detracted you from your project, because you can still do it, just need to work with the system here. Your hands become untied if you use counters (proto-variables) cleverly, if you use if() and while() commands in clever ways.
    Last edited by SigniferOne; 04-18-2007 at 18:32.

  6. #6

    Default Re: Newbie scripting question [LevyScript]

    Yup, been skimming them since last night. One thing I've noticed that doesn't exist is anyway to find out the actual population of a settlement, I've found equivalents for nearly everything else. Any clues?

  7. #7
    Harbinger of... saliva Member alpaca's Avatar
    Join Date
    Aug 2003
    Location
    Germany
    Posts
    2,767

    Default Re: Newbie scripting question [LevyScript]

    Yeah it's a minor problem. You can only use the settlement level via building exists

  8. #8

    Default Re: Newbie scripting question [LevyScript]

    Is there a method by which one can destroy a particular building? I want the muster call "building" to be destroyed the turn after it's created.

  9. #9

    Default Re: Newbie scripting question [LevyScript]

    An addendum, I've found the following;

    set_building_health London muster_call 0

    However, would this prevent the following monitor from triggering (since the building is built, its just broken):

    declare_counter muster_isbuilt
    set_counter muster_isbuilt 0
    monitor_event SettlementTurnStart SettlementName London
    and SettlementBuildingExists = muster_call
    set_counter muster_isbuilt 1
    set_building_health London muster_call 0
    end_monitor

    ie; does repairing also qualify as building?

  10. #10

    Default Re: Newbie scripting question [LevyScript]

    Can't you check the building health, instead?

  11. #11

    Default Re: Newbie scripting question [LevyScript]

    I can't find that command. Is it check_building_health, or some such?

  12. #12

    Default Re: Newbie scripting question [LevyScript]

    ok, so this is what I have so far, the top bits are something of a rip of Klink's garrison code as near as I could understand what he was doing, the rest are just a couple of test conditions for the english at London.

    Code:
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;; Declare some local variables
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    declare_counter Facnr
    set_counter Facnr 1
    declare_counter Facstart
    set_counter Facstart 1
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;; Figure out if this is the player's turn and what faction he belongs to
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    monitor_event FactionTurnStart FactionIsLocal
    set_counter Facstart 1
    	if I_LocalFaction england
    		set_counter Facnr 5
    	end_if
    end_monitor
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;; Find out if this is player's turn or AI's turn
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    monitor_event FactionTurnEnd FactionIsLocal
    	set_counter Facstart 0
    end_monitor
    
    if I_CompareCounter Facstart = 1
    set_counter Grrson 0
    end_if
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;; Find out if the settlement belongs to this faction
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    if I_CompareCounter Facnr = 5
    and I_SettlementOwner London = england 
      set_counter Grrson 1
    end_if
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;; Check if player has built the Muster Call structure and spawn an army if they have.
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    if I_CompareCounter muster_isbuilt = 1
    and I_CompareCounter London_lev = 1
    and I_SettlementOwner London = england
    and I_CompareCounter Grrson = 1
    	create_unit London, Peasants, num 4, exp 0, arm 0, wep 0
    	console_command add_money england, -400
    end_if
    if I_CompareCounter muster_isbuilt = 1
    and I_CompareCounter London_lev = 1
    and I_SettlementOwner London = england
    and I_CompareCounter Grrson = 1
    and I_CompareCounter gov_chivalry = 1
    	create_unit London, Peasants, num 8, exp 0, arm 0, wep 0
    	console_command add_money england, -800
    end_if
    
    ;;;;; Monitor events to check if player built muster call
    declare_counter muster_isbuilt
    set_counter muster_isbuilt 0
    monitor_event SettlementTurnStart SettlementName London
    and SettlementBuildingExists = muster_call
    set_counter muster_isbuilt 1
    set_building_health London muster_call 0
    end_monitor
    
    ;;;;; 
    declare_counter London_lev
    set_counter London_lev 0
    monitor_event SettlementTurnStart SettlementName London
    and SettlementBuildingExists = wooden_walls
    set_counter London_lev 1
    end_monitor
    
    declare_counter gov_chivalry
    monitor_event SettlementTurnStart SettlementName London
    and GovernorAttribute Chivalry >= 1
    set_counter gov_chivalry 1
    end_monitor
    Do you think this could work?

  13. #13

    Default Re: Newbie scripting question [LevyScript]

    The code is abit confusing because you have events interspersed throughout the code. Try to always keep them at the top, for readability's sake. Also I don't know if you can use 'and' clauses in if statements, but I suppose it's possible. Even if not, can use nested 'if' instead, same thing.

    Alright I think I get what you're trying to do in your script: have a building called 'legion', you build that building and a full legion instantly pops up, is that right?

    Secondly remember, those if_statements will not be triggered once the variable acquires a new value. They will be run through once at the beginning of the script (not beginning of turn), and that's it. A better option is to use 'while' to spin loops until a variable is set as you want it.

    Third, these three clauses do unnecessary work:

    Code:
    monitor_event FactionTurnStart FactionIsLocal
    set_counter Facstart 1
    	if I_LocalFaction england
    		set_counter Facnr 5
    	end_if
    end_monitor
    
    ---------------------------------------------------
    
    monitor_event FactionTurnEnd FactionIsLocal
    	set_counter Facstart 0
    end_monitor
    
    if I_CompareCounter Facstart = 1
    set_counter Grrson 0
    end_if
    
    ---------------------------------------------------
    
    if I_CompareCounter Facnr = 5
    and I_SettlementOwner London = england 
      set_counter Grrson 1
    end_if
    Think of it like a state machine. You basically want to get to the state where you can say "Grrson = 1", only if local faction, england, and owning London. Simply replace the above code with:

    Code:
    monitor_event FactionTurnStart FactionIsLocal
                        and LocalFaction england
    
              if I_SettlementOwner London = england
                 set_counter Grrson 1
              end_if
    
    end_monitor
    Then, even better than spinning wheels with while(), just do:

    Code:
    monitor_condition EventCounter Grrson > 1 TrueCondition
       ; check counters for settings, and build an army accordingly
    
       set_counter Grrson = 0
    end_monitor

    NB. I got the syntax for that monitor_condition off the top of my head, might want to tinker with the syntax to make it execute, but I think it's mostly right.
    Last edited by SigniferOne; 04-19-2007 at 03:37.

  14. #14

    Default Re: Newbie scripting question [LevyScript]

    maybe I'm just being obtuse, but I added;
    Code:
    monitor_event FactionTurnStart FactionIsLocal
                        and LocalFaction england
    
              if I_SettlementOwner London = england
                 set_counter Grrson 1
                 console_command add_money england, 50000
              end_if
    end_monitor
    to check if the event was ever triggering, but it seems that it never does. Can't for the life of me figure out why (I always start a new game with england and let a turn lapse).

    Is there anyway to print directly to the command line just to see if the even is ever firing?

  15. #15

    Default Re: Newbie scripting question [LevyScript]

    console_command puppify_my_love (the command was created for that very purpose, as far as I know, to test if things fire).

    Oh, the reason your code isn't firing is because FactionIsLocal is a condition, not an event. Change to:

    Code:
    monitor_event FactionTurnStart FactionType england
                        and FactionIsLocal TrueCondition
    
              if I_SettlementOwner London = england
                 set_counter Grrson 1
                 console_command add_money england, 50000
              end_if
    end_monitor
    Last edited by SigniferOne; 04-19-2007 at 04:07.

  16. #16

    Default Re: Newbie scripting question [LevyScript]

    I'm working with a clean (vanilla) campaign script file and its still not firing, any clues?

  17. #17

    Default Re: Newbie scripting question [LevyScript]

    Apply typical code debugging tools :) delete some of the clauses, see what happens. Remove local facition thingy clause in event trigger, have it fire, then find the right syntax to add it back in. I'm 99% certain the faction clause syntax is correct.

  18. #18
    Harbinger of... saliva Member alpaca's Avatar
    Join Date
    Aug 2003
    Location
    Germany
    Posts
    2,767

    Default Re: Newbie scripting question [LevyScript]

    First of all: Enable error logging. To do this you have to add the following to your config:
    Code:
    [log]
    to = logs/m2.log.txt
    level = * error
    As for your monitor: iirc console_command doesn't use a comma

  19. #19

    Default Re: Newbie scripting question [LevyScript]

    if you don't find a debug error make sure you included the wait_monitors. I hit that one before and took me ages to realise.

    ;
    ; Campaign script
    ;
    script


    declare_counter Grrson 1

    monitor_event FactionTurnStart FactionType england
    and FactionIsLocal TrueCondition

    if I_SettlementOwner London = england
    set_counter Grrson 1
    console_command add_money england, 50000
    end_if
    end_monitor


    wait_monitors


    end_script

  20. #20

    Default Re: Newbie scripting question [LevyScript]

    Awrighty, i got it spawning peasants when I build the Muster Call structure, then dropping the structure's health to 0, unfortunately it continues spawning peasants as long as the building exists. Is there a way to check the building's health?

    ie; check_building_health muster_call 0

    or some such.

  21. #21

    Default Re: Newbie scripting question [LevyScript]

    Hold up everyone. I think you can still destroy a structure, despite the fact that there is no command to destroy it. I just realized that a player can destroy the structure, by clicking the 'destroy' button, and there is a way to invoke GUI buttons from inside the script!

    I don't have time this instant to follow this idea through, but I think it could definitely be possible.
    Last edited by SigniferOne; 04-19-2007 at 18:27.

  22. #22

    Default Re: Newbie scripting question [LevyScript]

    Right, I remember the EB team did something like this way back during the development of .7 for RTW, of course, I have no idea how, but it definitely seems possible.

    Back to my earlier question;

    The monitor_event I'm using just checks if the buildign exists within the settlement, is there a way to check if it was built/repaired in the last turn instead?

  23. #23
    Harbinger of... saliva Member alpaca's Avatar
    Join Date
    Aug 2003
    Location
    Germany
    Posts
    2,767

    Default Re: Newbie scripting question [LevyScript]

    Well if you ask me, the best way to do this would be reverting the process (as there's no destroy_building command and you can't check building health):
    You can trigger your script off the destruction of your building, and the player can build it again at a later time (actually I'll create the building by script after a cooldown period). The problem with that is of course that the player can kind of "store" his army because he can build it at any time and destroy it in an instant.
    As for pressing buttons: This is very unstable code in general. I'm also not sure if you can actually choose a building to open the building scroll (which you'd have to do if you want to destroy it), I think I tried that back in the RTW times and couldn't get it to work.

  24. #24

    Default Re: Newbie scripting question [LevyScript]

    Hmm, is there anyway to count the number of turns a building has existed then?

    If so, one thing you could do is have the building itself have a huge upkeep every turn its in play, then base the troop spawn on how long you've had the building before you destroy it. Players would be encouraged to only build them when necessary, since the cost of mustering a huge army then keeping it over time would be huge, and you don't have the benefit of being able to individually reshuffle/disband units as you would with an army of individual units.

    Taking it a step further, The building might also add to unrest/squalor, or have some other negative penalties that force players to be fairly pragmatic about using them.

    But I digress, I have no idea which conditions would work for such a thing. :)

  25. #25

    Default Re: Newbie scripting question [LevyScript]

    So I've had a go at the new condition, but something is still eluding me. I'm trying to have it check if a player has destroyed the building during their turn, to do this, I'm using the following events;

    Code:
    ;;;;; Check if Muster call exists (at the beginning of the turn)
    set_counter muster_exists 0
    monitor_event SettlementTurnStart SettlementName London
    and SettlementBuildingExists = muster_call
    set_counter muster_exists 1
    end_monitor
    
    ;;;;; Check of muster Call does not exist (at the end of the turn)
    declare_counter muster_dne
    set_counter muster_dne 0
    monitor_event SettlementTurnEnd SettlementName London
    and not SettlementBuildingExists = muster_call
    set_counter muster_dne 1
    end_monitor
    
    ;;;;; Check if Muster Call was destroyed between the start and end of the player's turn
    monitor_event SettlementTurnStart SettlementName London
    	if I_CompareCounter muster_exists = 1
    	and I_CompareCounter muster_dne = 1
    		console_command puppify_my_love
    	end_if
    end_monitor
    I know the first monitor_event works correctly, the problem is that the second doesn't appear to be firing correctly, so as a result, I'm getting puppies when I shouldn't be getting 'em (cute as they are).

  26. #26

    Default Re: Newbie scripting question [LevyScript]

    Damn th elack of an edit feature;

    I tried a different, equally unsuccessful vector of attack, this time no puppies. Am I misunderstanding how the BuildingDestroyed flag works?

    Code:
    declare_counter muster_destroyed
    set_counter muster_destroyed 0
    monitor_event SettlementTurnEnd SettlementName London
    and BuildingDestroyed = muster_call
    	set_counter muster_destroyed 1
    end_monitor
    
    monitor_event FactionTurnEnd FactionType england
    and I_LocalFaction england
    if I_CompareCounter muster_destroyed 1
    	console_command puppify_my_love
    end_monitor

  27. #27

    Default Re: Newbie scripting question [LevyScript]

    PROGRESS!

    I've gotten the basic functions of th elevy script working, as of right now, you build a muster_call building, then demolish it and you get units! I'm currently coming up with a bonus/penalty scheme to make it all nice n' balanced, but here's the campaign script code as of right now:

    Code:
    ;=============================================================
    ;=        O     Levy Script by Alex Drake                    =
    ;=============================================================
    
    ;=============================================================
    ;	Declare some local variables
    ;=============================================================
    declare_counter Facnr
    set_counter Facnr 1
    declare_counter Facstart
    set_counter Facstart 0
    declare_counter Grrson
    set_counter Grrson 0
    
    ;=============================================================
    ;	Figure out if this is the player's turn and what faction he belongs to
    ;=============================================================
    
    
    monitor_event FactionTurnStart FactionType england
                        and FactionIsLocal TrueCondition
    		;console_command puppify_my_love
    	if I_SettlementOwner London = england
    		set_counter Facstart 1
    		set_counter Facnr 5
    		set_counter Grrson 1
    		;console_command add_money england, 50000
              end_if
    end_monitor
    
    ;=============================================================
    ;	
    ;=============================================================
    
    declare_counter muster_exists
    set_counter muster_exists 0
    monitor_event SettlementTurnStart SettlementName London
    and SettlementBuildingExists = muster_call
    set_counter muster_exists 1
    
    end_monitor
    
    declare_counter muster_dne
    set_counter muster_dne 0
    monitor_event SettlementTurnEnd SettlementName London
    and not SettlementBuildingExists = muster_call
    
    set_counter muster_dne 1
    end_monitor
    
    declare_counter London_lev
    set_counter London_lev 0
    monitor_event SettlementTurnStart SettlementName London
    and SettlementBuildingExists = wooden_wall
    set_counter London_lev 1
    end_monitor
    
    declare_counter gov_chivalry
    monitor_event SettlementTurnStart SettlementName London
    and GovernorAttribute Chivalry >= 1
    set_counter gov_chivalry 1
    end_monitor
    
    ;=============================================================
    ;;;;; Monitor events to check if player built muster call
    ;=============================================================
    
    declare_counter muster_destroyed
    set_counter muster_destroyed 0
    monitor_event SettlementTurnEnd SettlementName London
    and not SettlementBuildingExists = muster_call
    	set_counter muster_destroyed 1
    	;console_command puppify_my_love
    end_monitor
    
    monitor_event FactionTurnEnd FactionType england
    and I_LocalFaction england
    if I_CompareCounter muster_destroyed 1
    	;console_command puppify_my_love
    	console_command add_money england, 50000
    	end_if
    end_monitor
    
    
    
    monitor_event FactionTurnEnd FactionType england
    and I_LocalFaction england
    	if I_CompareCounter muster_exists = 1
    	and I_CompareCounter muster_dne = 1
    		create_unit London, Peasants, num 4, exp 1, arm 0, wep 0
    		create_unit London, Town Militia, num 2, exp 6, arm 0, wep 0
    		if I_CompareCounter gov_chivalry = 1
    			create_unit London, Spear_Militia, num 1, exp 2, arm 0, wep 0
    		end_if
    		;console_command puppify_my_love
    	end_if
    end_monitor
    suggestions?

  28. #28
    Harbinger of... saliva Member alpaca's Avatar
    Join Date
    Aug 2003
    Location
    Germany
    Posts
    2,767

    Default Re: Newbie scripting question [LevyScript]

    1) Use the BuildingDestroyed event. Much more useful and works instantly
    2) Keep in mind that buildings often can't give negative bonuses. I think for example that income_bonus doesn't work with negative numbers

  29. #29

    Default Re: Newbie scripting question [LevyScript]

    Whenever I use BuildingDestroyed, the entire statement fails to trigger. From the research I did, it seems building destroyed only works with event triggers, not monitor events in the campaign_script file (ie; when you destroy a church, you lose favor with the pope. This is an actual event).

    As for negative bonuses, I was just going to do it in the campaign_script file itself, then include the info in the building description. (ie; check for the number of these buildings the player has, then subtract money based on that).

  30. #30
    Harbinger of... saliva Member alpaca's Avatar
    Join Date
    Aug 2003
    Location
    Germany
    Posts
    2,767

    Default Re: Newbie scripting question [LevyScript]

    monitor_event BuildingDestroyed TrueCondition
        console_command add_money 40000
    end_monitor

    Works fine for me...

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Single Sign On provided by vBSSO