[SCRIPT] Force a champion to own the scroll before casting

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!
cameronC
Posts: 80
Joined: Wed Apr 11, 2012 10:54 pm

Re: [SCRIPT] Force a champion to own the scroll before casti

Post by cameronC »

TSotP wrote:that's awesome, thanks guys.

i do have another related question.

would that script return true if the spell scroll was in a container? The reason i ask, is i wonder if i could make a modified 'wooden box' or 'sack' as a spellbook for the scrolls Nevermind, the answer is no.
You can make it so that if the item in the champions inventory is a container (By name/id, or if getComponent("containeritem") or however) then it goes through that item slot by slot for the scroll.


Thank you for this! It got me started on something I was wanting to get around to. Here is the first version of a staff that will only let the wielder cast the spells they have placed into it.

Runewand:

Code: Select all

defineObject{
       name = "runewand_sk",
       baseObject = "base_item",
       components = {
        {
        class = "Model",
        model = "assets/models/items/acolyte_staff.fbx",
        },
   {
        class ="Item",
        uiName = "Runewand",
        gfxIndex = 340,
		weight = 2.7,
        impactSound = "impact_blunt",
        traits = { "stave", "light_weapon" },
        secondaryAction = "castPrimaryRune",
        description = "A simple Runewand once used by an apprentice mage."
        },
        {
        class = "RunePanel",
        },
		{
		class = "EquipmentItem",
		slot = 1,
		},
		{
		class = "ContainerItem",
		containerType = "sack",
		},
        }
    }
onCastSpell:

Code: Select all

defineObject{
   name = "party",
   baseObject = "party",
   components = {
      {
         class = "Party",  
         onCastSpell =
            function(party,champion,spellName)         
               local allRunecasters = { "runewand_sk" }   
			   local itmName = ""
               local spellUiName = ""
			   local equippedRunecaster = ""
               
               if spellName == "water_breathing" then
                  itmName = "scroll_water_breathing"
                  spellUiName = "Water Breathing"
               end
               if spellName == "resurrection" then
                  itmName = "scroll_resurrection"
                  spellUiName = "Resurrection"
               end
               if spellName == "antidote" then
                  itmName = "scroll_antidote"
                  spellUiName = "Antidote"
               end
               if spellName == "recovery" then
                  itmName = "scroll_recovery"
                  spellUiName = "Recovery"
               end
               if spellName == "antivenom" then
                  itmName = "scroll_antivenom"
                  spellUiName = "Antivenom"
               end
               if spellName == "enchant_arrow" then
                  itmName = "scroll_enchant_arrow"
                  spellUiName = "Enchant Arrow"
               end
               if spellName == "heal" then
                  itmName = "scroll_heal"
                  spellUiName = "Healing"
               end
               if spellName == "mass_heal" then
                  itmName = "scroll_mass_heal"
                  spellUiName = "Mass Healing"
               end
               if spellName == "shield" then
                  itmName = "scroll_shield"
                  spellUiName = "Shield"
               end
               if spellName == "force_field" then
                  itmName = "scroll_force_field"
                  spellUiName = "Force Field"
               end
               if spellName == "fireburst" then
                  itmName = "scroll_fireburst"
                  spellUiName = "Fireburst"
               end
               if spellName == "light" then
                  itmName = "scroll_light"
                  spellUiName = "Light"
               end
               if spellName == "darkness" then
                  itmName = "scroll_darkness"
                  spellUiName = "Darkness"
               end
               if spellName == "darkbolt" then
                  itmName = "scroll_darkbolt"
                  spellUiName = "Darkbolt"
               end
               if spellName == "fireball" then
                  itmName = "scroll_fireball"
                  spellUiName = "Fireball"
               end
               if spellName == "meteor_storm" then
                  itmName = "scroll_meteor_storm"
                  spellUiName = "Meteor Storm"
               end
               if spellName == "shock" then
                  itmName = "scroll_shock"
                  spellUiName = "Shock"
               end
               if spellName == "invisibility" then
                  itmName = "scroll_invisibility"
                  spellUiName = "Invisibility"
               end
               if spellName == "lightning_bolt" then
                  itmName = "scroll_lightning_bolt"
                  spellUiName = "Lightning Bolt"
               end
               if spellName == "poison_cloud" then
                  itmName = "scroll_poison_cloud"
                  spellUiName = "Poison Cloud"
               end
               if spellName == "poison_bolt" then
                  itmName = "scroll_poison_bolt"
                  spellUiName = "Poison Bolt"
               end
               if spellName == "ice_shards" then
                  itmName = "scroll_ice_shards"
                  spellUiName = "Ice Shards"
               end
               if spellName == "dispel" then
                  itmName = "scroll_dispel"
                  spellUiName = "Dispel"
               end
               if spellName == "frostbolt" then
                  itmName = "scroll_frostbolt"
                  spellUiName = "Frostbolt"
               end
               if spellName == "fire_shield" then
                  itmName = "scroll_fire_shield"
                  spellUiName = "Fire Shield"
               end
               if spellName == "shock_shield" then
                  itmName = "scroll_shock_shield"
                  spellUiName = "Shock Shield"
               end
               if spellName == "poison_shield" then
                  itmName = "scroll_poison_shield"
                  spellUiName = "Poison Shield"
               end
               if spellName == "frost_shield" then
                  itmName = "scroll_frost_shield"
                  spellUiName = "Frost Shield"
               end

				if champion:getItem(1) == nil then 
					hudPrint("You must have a Runecaster equipped.")
					return false
				end
			    for i = 1, #allRunecasters do
					if champion:getItem(1).go.name == allRunecasters[i] then 
						
						local runeCapacity = champion:getItem(1).go.containeritem:getCapacity()
						for j = 1, runeCapacity do
							
							local checkItem = champion:getItem(1).go.containeritem:getItem(j)
							if checkItem ~= nil then
								if checkItem.go.name == itmName then
								return true
							end
						end
					end			
				end
				end
			   
			   
               hudPrint("That rune is not slotted into your caster.")
               return false  
            end
      },
   },
}
So, Runewand is copied from Acolyte staff and given the containeritem component so when it is right clicked in the inventory it opens up to give you 9 slots (As far as we know we can only give a container 9 or 16 slots) and items can be placed inside the staff (I couldn't get it to only allow scrolls to be placed in it without the editor crashing on insert/remove...).

The code as is works 99% of the time. If you take an item from the staff and try to throw out into the world, the editor seems to crash. You have to place it in your inventory and then throw/drop it.

I tried integrating the streamlined code jkos wrote but kept getting an error I hadn't seen before ("bad self" I believe it was). I also tried to make it check if the item in slot 1 was ANY containeritem and also got an error, so I'm not sure how I managed to piece even this mostly working staff together given that any time I try to simplify it I make things crash. I hope to have it become a fairly versatile system, where spells and spell modifiers can be placed into a wand (Ideally with less/different slots than 9 or 16) to determine what spells a champion is able to cast.

Something like this is part of a collection of spells I'm in the middle of working on and Jhaelen's code gave me a nice starting point.
Last edited by cameronC on Sun Nov 16, 2014 6:54 pm, edited 1 time in total.
Writer and sometimes artist of the very slightly acclaimed comic series Scrambled Circuits. A comic series about a robot written by a human.

Grimrock 2 socketSystem: viewtopic.php?f=22&t=8546 / Github
User avatar
Aisuu
Posts: 61
Joined: Fri Oct 31, 2014 2:07 pm

Re: [SCRIPT] Force a champion to own the scroll before casti

Post by Aisuu »

Thats great idea. But fail. It need some code in hooks_sk script entity. Can you provide it?
Like this, editor crash when I try tu put scrool in staff container..
cameronC
Posts: 80
Joined: Wed Apr 11, 2012 10:54 pm

Re: [SCRIPT] Force a champion to own the scroll before casti

Post by cameronC »

Aisuu wrote:Thats great idea. But fail. It need some code in hooks_sk script entity. Can you provide it?
Like this, editor crash when I try tu put scrool in staff container..
My bad, I edited the above code. You can just remove the two calls to that, they arent relevant.
Writer and sometimes artist of the very slightly acclaimed comic series Scrambled Circuits. A comic series about a robot written by a human.

Grimrock 2 socketSystem: viewtopic.php?f=22&t=8546 / Github
User avatar
Aisuu
Posts: 61
Joined: Fri Oct 31, 2014 2:07 pm

Re: [SCRIPT] Force a champion to own the scroll before casti

Post by Aisuu »

cameronC, did you manage to work out your script alongside with Jhaelen script? It somehow worked for a while, but then your script didnt work at all.. It keep saying I need to put scroll inside the staff, even I had one inside.
cameronC
Posts: 80
Joined: Wed Apr 11, 2012 10:54 pm

Re: [SCRIPT] Force a champion to own the scroll before casti

Post by cameronC »

Aisuu wrote:cameronC, did you manage to work out your script alongside with Jhaelen script? It somehow worked for a while, but then your script didnt work at all.. It keep saying I need to put scroll inside the staff, even I had one inside.
Yeah, I'm in the middle of working that part out. As far as I can tell, that seems to happen when you start the editor with a scroll in the staff. If you start the editor with the staff open in your inventory window it shows the scrolls even though stuff inside containeritems *DO* get reset when the editor is restarted (As opposed to inventory items, which dont) so you end up with a staff that looks like it has scrolls in it but doesn't.

defineObject party:

Code: Select all

defineObject{
   name = "party",
   baseObject = "party",
   components = {
      {
         class = "Party",  
         onCastSpell =
            function(party,champion,spellName)         
               local allRunecasters = { "runewand_sk" }   
			   local itmName = "scroll_"..spellName  

				if champion:getItem(1) == nil then 
					hudPrint("You must have a Runecaster equipped.")
					return false
				end
			    for i = 1, #allRunecasters do
					if champion:getItem(1).go.name == allRunecasters[i] then 
						
						local runeCapacity = champion:getItem(1).go.containeritem:getCapacity()
						for j = 1, runeCapacity do
							local checkItem = champion:getItem(1).go.containeritem:getItem(j)
							if checkItem ~= nil then
									if checkItem.go.name == itmName then
									return true
								end
							end
						end
					end			
				end

               hudPrint("That rune is not slotted into your caster.")
               return false  
            end
      },
   },
}
Runewand definition:

Code: Select all

defineObject {
       name = "runewand_sk",
       baseObject = "base_item",
       components = {
        {
        class = "Model",
        model = "assets/models/items/acolyte_staff.fbx",
        },
          {
        class ="Item",
        uiName = "Runewand",
        gfxIndex = 340,
          weight = 2.7,
        impactSound = "impact_blunt",
        traits = { "stave", "light_weapon" },
        description = "A simple Runewand once used by an apprentice mage."
        },
        {
        class = "RunePanel",
        },
          {
          class = "EquipmentItem",
          slot = 1,
          },
          {
          class = "ContainerItem",
          containerType = "sack",
          onInsertItem = function(self, item, slot)
               
          end,
          onRemoveItem = function(self, item, slot) 
          
          end,
          },
        }
    }
The code isn't much different. More compact, a little cleaner, and uses "scroll_"..spellName instead of all the if/thens.

Now after playing around the only issue is the phantom scrolls, however, that seems to just be an issue with how the editor handles restarting itself (Though I have NOT yet exported and tested in a live environment, no indication that shouldnt keep the scrolls inside like every other containeritem does).

Things to do next would be to play around with defining spells that look at the staff of the caster and behave differently depending on the contents. For instance, if at least one "Minor Earth Mastery" scroll is in the staff then earth spells would be slightly more effective. or a protect spell that targets the caster normally but with a particular modifier scroll targets the whole party instead. Maybe a scroll that returns a little bit of energy to you after each successful spell you cast or something, etc etc. If we can define smaller container capacities I think it gets pretty interesting, rebuilding your staff loadout for each scenario you are in, dividing the available scrolls between multiple mages, etc.

And of course, this can maybe later be expanded to a diablo 2-esque socket system for various types of equipment eventually. I'm sure it's already very possible to make a set of gloves that are containeritems that, onInsertItem, checks if a certain type of item was inserted then disables its own containeritemcomponent and sets a stat modifier based on what item was placed in it.
Writer and sometimes artist of the very slightly acclaimed comic series Scrambled Circuits. A comic series about a robot written by a human.

Grimrock 2 socketSystem: viewtopic.php?f=22&t=8546 / Github
User avatar
akroma222
Posts: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: [SCRIPT] Force a champion to own the scroll before casti

Post by akroma222 »

cameronC wrote:
TSotP wrote:
The code as is works 99% of the time. If you take an item from the staff and try to throw out into the world, the editor seems to crash. You have to place it in your inventory and then throw/drop it.
CameronC - I have come up with a similar script for my spell casting.... but I ran into issues with the game crashing when you remove items from the container and place/throw them into the world
... did you find out why this is happening and if so any fixes for it....
Slava
Posts: 21
Joined: Sun Aug 30, 2015 2:10 pm

Re: [SCRIPT] Force a champion to own the scroll before casti

Post by Slava »

не хочу переводить, кому надо - тот поймет :D
я немного модернизировал ваш код

Code: Select all

do
local SPELLNAME = {"inner_fire","fireburst","warmth","summon_fire_staff","pyro_metabolism","caecare","heat","fire_enhancement","fireball","fire_charge","fire_shield","burn_aura","blaze","ifrit_conversionis","EFA","haste","meteor_storm","my_fire_wall","fire_temple","the_curse_of_fire","Melt","fire_rune","magmaball","phoenix_reborn","fire_absorption","fire_barrier"}

	for i = 1, #SPELLNAME  do
		defineObject{
		name = "scroll_"..SPELLNAME[i],
		baseObject = "scroll_light",
		components = {
				{
					class = "Item",
					uiName = "Scroll of "..SPELLNAME[i],
					gfxAtlas = "assets/textures/gui/items.tga",
					gfxIndex = 113,
					weight = 0.3,
				},
				{
					class = "SpellScrollItem",
					spell = SPELLNAME[i],
				},
				{
					class = "UsableItem",
					onUseItem = function(self, champion)
						if champion:hasTrait(SPELLNAME[i].." spell") then
							hudPrint(champion:getName().." already know this spell")
							playSound("spell_fizzle")
						return false end
						if not champion:hasTrait(SPELLNAME[i].." spell") then
							playSound("discover_spell")
							hudPrint(champion:getName().." learn new spell!")
							champion:addTrait(SPELLNAME[i].." spell")
						return true end					
					end,
				},
			},
		tags = { "My_scroll" },
		}
	end
	
	for i = 1, #SPELLNAME  do
		defineTrait{
		name = SPELLNAME[i].." spell",
		uiName = SPELLNAME[i],
		icon = 0,
		description = "",
		hidden = true,
		}
	end
	
end
А это нужно вставить в Party hook

Code: Select all

onCastSpell = function(self, champion, spellName)
			if champion:hasTrait(spellName.." spell") then return self, champion, spellName end
			return false end,
Post Reply