Starting a new mod with only 1 champion

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
Post Reply
billb52

Starting a new mod with only 1 champion

Post by billb52 »

Can anyone help? I am trying to start a mod with only 1 champion then others joining later, how do I script this? after picking my champions then having champions 2,3, and 4 disabled then later finding them and re-enabling them to join party. I have looked at
the scripting reference on 'Champions' but do not understand how to use it. pls Help!
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: Starting a new mod with only 1 champion

Post by Isaac »

Try this one:

Place in a script entity on the map. Alter the character values to suit. You can change the enabled value to 'disable', and enable them later, as the PCs are recruited. For custom portraits, you must ensure the .dds image files are present, and named correctly; using the same naming convention as the the others in the game.

Code: Select all

--Set a Custom Party: version 0.9a
--By Isaac


function setCustomPC()
   local function rnd(min,max) if max then return math.random(min,max) else return math.random(min) end end
   local characters = {
                        {--PC #1 
                         enabled = true,  
                         name = "test1",
                         race = "minotaur",
                         sex  = "male",
                         class = "farmer",
                         portrait = "minotaur_male_02",
                         isCustomPortrait = false,
                         stats = {strength = rnd(15), dexterity = rnd(15), vitality = 56, willpower = rnd(15)}, --remember to account for racial Stat Bonuses!
                         traits = {"head_hunter",},
                         skills = {
                                    alchemy=0, accuracy=1, athletics=3, critical=0, 
                                    concentration=0, light_weapons=0, heavy_weapons=2, 
                                    missile_weapons=0, throwing=0, firearms=0, armors=2,
                                    earth_magic=0, water_magic=0, fire_magic=0, dodge=0,
                                    air_magic=0,
                                  },
                         equipped = {
                                    "hand_axe", --Weapon 
                                    "", -- OffHand
                                    "peasant_cap", --Head
                                    "leather_brigandine", --Chest
                                    "", --Legs
                                    "", --Feet
                                    "", --Cloak
                                    "", --Necklace
                                    "leather_gloves", --Gloves
                                    "", --Bracers
                                    "fire_bomb", --Weapon2
                                    "", --Offhand2
                                    },
                         Backpack = {"dagger", "pitroot_bread","dagger", "pitroot_bread","dagger", "pitroot_bread",
                                                "dagger", "pitroot_bread","dagger", "pitroot_bread","dagger", "pitroot_bread",
                                                "dagger", "pitroot_bread","dagger", "pitroot_bread","dagger", "pitroot_bread",
                                                "dagger", "potion_healing",}, -- 20 comma separated items max         
                        },

                        {--PC #2
                         enabled = true,
                         name = "test2",
                         race = "minotaur",
                         sex  = "male",
                         class = "fighter",
                         portrait = "minotaur_male_11",
                         isCustomPortrait = true,
                         stats = {strength = 20, dexterity = rnd(6,20), vitality = rnd(15,22), willpower = rnd(20)}, 
                         traits = {"head_hunter",},
                         skills = {
                                    alchemy=0, accuracy=0, athletics=2, critical=1, 
                                    concentration=0, light_weapons=2, heavy_weapons=1, 
                                    missile_weapons=0, throwing=0, firearms=1, armors=2,
                                    earth_magic=0, water_magic=0, fire_magic=0, dodge=0,
                                    air_magic=0,
                                  },
                         equipped = {
                                    "dagger", --Weapon 
                                    "", -- OffHand
                                    "peasant_cap", --Head
                                    "", --Chest
                                    "", --Legs
                                    "", --Feet
                                    "", --Cloak
                                    "", --Necklace
                                    "", --Gloves
                                    "", --Bracers
                                    "", --Weapon2
                                    "", --Offhand2
                                    },
                         Backpack = {"dagger", "pitroot_bread", "potion_healing",},-- 20 comma separated items max          
                        },

                        {--PC #3
                         enabled = true,
                         name = "test3",
                         race = "insectoid",
                         sex  = "female",
                         class = "rogue",
                         portrait = "insectoid_female_03",
                         isCustomPortrait = false,
                         stats = {strength = rnd(16), dexterity = rnd(6,20), vitality = 16, willpower = rnd(16,20)}, 
                         traits = {},
                         skills = {
                                    alchemy=3, accuracy=3, athletics=0, critical=1, 
                                    concentration=4, light_weapons=0, heavy_weapons=0, 
                                    missile_weapons=0, throwing=0, firearms=0, armors=2,
                                    earth_magic=0, water_magic=0, fire_magic=0, dodge=1,
                                    air_magic=0,
                                  },
                         equipped = {
                                    "dagger", --Weapon 
                                    "", -- OffHand
                                    "peasant_cap", --Head
                                    "", --Chest
                                    "", --Legs
                                    "", --Feet
                                    "", --Cloak
                                    "", --Necklace
                                    "", --Gloves
                                    "", --Bracers
                                    "", --Weapon2
                                    "", --Offhand2
                                    },
                         Backpack = {"dagger", "pitroot_bread", "potion_healing",},-- 20 comma separated items max          
                        },

                        {--PC #4
                         enabled = true,
                         name = "test4",
                         race = "human",
                         sex  = "female",
                         class = "wizard",
                         portrait = "human_female_03",
                         isCustomPortrait = false,
                         stats = {strength = 20, dexterity = rnd(6,20), vitality = 16, willpower = rnd(15,20)}, 
                         traits = {},
                         skills = {
                                    alchemy=1, accuracy=3, athletics=1, critical=0, 
                                    concentration=4, light_weapons=0, heavy_weapons=0, 
                                    missile_weapons=0, throwing=0, firearms=0, armors=0,
                                    earth_magic=1, water_magic=0, fire_magic=2, dodge=1,
                                    air_magic=1,
                                  },
                         equipped = {
                                    "dagger", --Weapon 
                                    "", -- OffHand
                                    "peasant_cap", --Head
                                    "", --Chest
                                    "", --Legs
                                    "", --Feet
                                    "", --Cloak
                                    "", --Necklace
                                    "", --Gloves
                                    "", --Bracers
                                    "", --Weapon2
                                    "", --Offhand2
                                    },
                         Backpack = {"dagger", "pitroot_bread", "potion_healing",},-- 20 comma separated items max          
                        },
                     }
                        

--**************************************************************************************
   local function setEnabledPCs()
      for x,PC in pairs(characters) do
         local champ = party.party:getChampion(x)
         champ:setEnabled(PC["enabled"])
      end   
   end   
   setEnabledPCs()

   local function setSkills(champ, skills)
      for k,v in pairs(skills) do
         champ:trainSkill(k,champ:getSkillLevel(k)*-1, false)
         champ:trainSkill(k,v)
      end
      champ:upgradeBaseStat("health", champ:getMaxHealth()-champ:getHealth())
      champ:upgradeBaseStat("energy", champ:getMaxEnergy()-champ:getEnergy())
      champ:setSkillPoints(0) 
   end
   local function setStats(champ, stats)
      for k,v in pairs(stats) do
         champ:setBaseStat(k,v)
      end
   end            
   for pos,PC in pairs(characters) do
      local champ = party.party:getChampion(pos)

      if champ:getEnabled() then
         champ:setRace(PC["race"])
         champ:setName(PC["name"])
         champ:setSex(PC["sex"])
         local filepath = iff(characters[pos]["isCustomPortrait"],"mod_","").."assets/textures/portraits/"..characters[pos]["portrait"]..".tga"
         champ:setPortrait(filepath)
         champ:setClass(PC["class"])
         setStats(champ, PC["stats"])
         setSkills(champ, PC["skills"])
         if #PC["traits"] > 0 then
            for x = 1, #PC["traits"] do
               champ:addTrait(characters[pos]["traits"][x])
            end   
         end
           
         for x = 1,12 do
            if #PC["equipped"][x] > 0 then   
               champ:insertItem(x,spawn(PC["equipped"][x]).item)
            end
         end

         if #PC["Backpack"] then   
            for x = 1, #PC["Backpack"] do
                 champ:insertItem(x+12,spawn(PC["Backpack"][x]).item)
            end
         end  
      end   
   end
   for x=1,5 do hudPrint("") end
   delayedCall(self.go.id, .2, "fixHealth")
end

function fixHealth()
   for x = 1, 4 do
      local champ = party.party:getChampion(x)
      if champ:getEnabled() then
         champ:setHealth(champ:getMaxHealth())
         champ:setEnergy(champ:getMaxEnergy())
      end 
   end 
end 

delayedCall(self.go.id, .1, "setCustomPC") 
It is a really good (and polite) idea to make it very clear in the mod's description, (where the player selects it to play), that you warn them that the mod overwrites a pre-made party; so not to bother making a party of their own.
billb52

Re: Starting a new mod with only 1 champion

Post by billb52 »

Thankyou Isaac I will try it out.
Update:
Tried out and succeeded in getting 1st character OK with my preferred stats etc. But I cannot figure out how to recruit my
2nd PC ie. by using a lever to open prison door to release character 2, do I need a second script connected to lever? if so
how do I script it? pls help, thx in advance.

Once again Isaac you came to my rescue! much appreciated thx. for your help.
Last edited by billb52 on Sun Oct 07, 2018 7:58 pm, edited 1 time in total.
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: Starting a new mod with only 1 champion

Post by Isaac »

If the other PCs are set as disabled, then you must call: setEnabled(true) for the champion you wish to enable. This must be done from a script; and done for the intended champion. The player might have moved their position, so you should not pick them by their slot in the party.

There is an easy way to select a champion, regardless of where they may have moved, it uses their ordinal number (that is assigned to them when the game starts—it does not change). It is their position where they start the game. Their ordinal is (and remains) the same for the entire game.

So this call (for example), will enable the #2 PC wherever they are in the party.

Code: Select all

party.party:getChampionByOrdinal(2):setEnabled(true)


Calls from connected levers and triggers must be in a function, so a simple way to enable your PCs is to make a function for each connected lever or trigger that releases a PC.

Code: Select all

function releasePC1()
	party.party:getChampionByOrdinal(1):setEnabled(true)
end
function releasePC2()
	party.party:getChampionByOrdinal(2):setEnabled(true)
end
function releasePC3()
	party.party:getChampionByOrdinal(3):setEnabled(true)
end
function releasePC4()
	party.party:getChampionByOrdinal(4):setEnabled(true)
end
A more compact way to do this requires that the levers or triggers be specifically identified by some means.

This script should work, if the object ID of each connected trigger includes the identifier: PC1, or PC2, or PC3, or PC4 appended to the end of it.
Like this: release_lever_for_PC2

Code: Select all

function releasePC(trigger)
	local ID = trigger.go.id:match("PC%d$")
	if ID then party.party:getChampionByOrdinal(tonumber(ID:match('%d'))):setEnabled(true) end
end
The first line assigns the variable ID with any match found (in the calling trigger's ID) of the letter 'P' followed by a 'C', and then followed by a number; and checks that these are only the very last characters of the id string. The second line first checks that there was a match, then it extracts the number from it, and uses it as the numerical argument for getChampionByOrdinal(). You can connect all of your buttons, floor_triggers, and levers to this same script function—so long as each one is named correctly to indicate which champion to enable.

*Note: The script does not check that the number is only 1-4; but of course no other numbers will work.
Post Reply