Jump to content

Archery Mod: Discussion, Feedback and Thoughts


Recommended Posts

4 hours ago, ZupaleX said:

I'm not sure what you want to achieve. You want to add a bonus to the damage in one of your mod for a specific character? weapon? condition?

https://forums.kleientertainment.com/topic/83642-mod-comision/?do=findComment&comment=969730

I simply would like to make mods, that gives players eg a Damagemodifier with help of your code.
But I fear, if I do 2 mods (in one critters give damagemodifier to players and in another something else is giving modifiers to players) both mods would conflict with each other, if they both have this combat component adjustment.
Or do they not conflict?

I'm not sure about what happens if two or more mods have exactly your code... I thought it would conflict.

 

Edited by Serpens
Link to comment
Share on other sites

8 hours ago, Serpens said:

https://forums.kleientertainment.com/topic/83642-mod-comision/?do=findComment&comment=969730

I simply would like to make mods, that gives players eg a Damagemodifier with help of your code.
But I fear, if I do 2 mods (in one critters give damagemodifier to players and in another something else is giving modifiers to players) both mods would conflict with each other, if they both have this combat component adjustment.
Or do they not conflict?

I'm not sure about what happens if two or more mods have exactly your code... I thought it would conflict.

I actually have a snippet of code that I used for a personal mod of mine that might help you.

I have this little mod that has a collection of small changes to the game I like to make for my own server (I've thought about publishing them, just haven't gotten around to it :D) and one of the changes I added was to be able to do more damage to a treeguard when using a hatchet (as well as making a woodcutting sound for confirmation that you're doing more damage). However, because the "onattack" callback doesn't happen until after the damage was already done, it wouldn't apply the increased damage until after the first attack was made. Then if you were to attack anything other than a treeguard after that, it would do the increased damage first and then adjust itself when the "onattack" callback is made.

So, to fix this I pretty much just made my own callback to the combat.lua that happens before everything else when you attack that would adjust the damage accordingly to your target. The code goes as follows:

Spoiler

-- This adds the callback "onproc" to the function "DoAttack" in the "combat" component using a wrapper
-- Its more or less identical to the "onattack" callback, but runs before anything else

function CombatCompPostInit(comp)
	local old_DoAttack = comp.DoAttack

	comp.DoAttack = function(self, target_override, weapon, projectile, stimuli, instancemult)
		local targ = target_override or self.target
    	local weapon = weapon or self:GetWeapon()

    	if weapon and weapon.components.weapon and weapon.components.weapon.onproc then
    		weapon.components.weapon:OnProc(self.inst, targ)
    	end
    	old_DoAttack(self, target_override, weapon, projectile, stimuli, instancemult)
	end
end
AddComponentPostInit("combat", CombatCompPostInit)


-- This will allow you to declare and call an "onproc" function in the instances "weapon" component

function WeaponCompPostInit(comp)
	comp.onproc = nil

	comp.SetOnProc = function(self, fn)
		self.onproc = fn
	end

	comp.OnProc = function(self, attacker, target)
		if self.onproc then
			self.onproc(self.inst, attacker, target)
		end
	end
end
AddComponentPostInit("weapon", WeaponCompPostInit)


-- Then, you just declare whatever function youd like to call whenever you attack and use the weapon:SetOnProc() function to assign it
-- Ill give you the example out of my mod that changes the damage when attacking a treeguard with an axe (it applies to other forms of
-- axes too but those arent relevant for this example lol)

function AxePrefabPostInit(inst)
	local function onproc(axe, attacker, target)
		if GetModConfigData("LEIF_AXE_DAMAGE") ~= 1 then
			if target.prefab == "leif" or target.prefab == "leif_sparse" then
				axe.components.weapon:SetDamage(TUNING.AXE_DAMAGE * GetModConfigData("LEIF_AXE_DAMAGE"))
				target.SoundEmitter:PlaySound("dontstarve/wilson/use_axe_tree")
			else
				axe.components.weapon:SetDamage(TUNING.AXE_DAMAGE)
			end
		else
			axe.components.weapon:SetDamage(TUNING.AXE_DAMAGE)
		end
	end
	
	if GLOBAL.TheWorld.ismastersim then
		inst.components.weapon:SetOnProc(onproc)
	end
end
AddPrefabPostInit("axe", AxePrefabPostInit)

 

For your case, what you'll probably want to do is first store the original damage value to a local variable in your PostInit function. Then in your "onproc" function, create a check that checks for the particular critter that's following you, and if it is, use the weapon:SetDamage() function to set the damage to the locally stored damage variable * your multiplier:

Spoiler

function PrefabPostInit(inst) -- whatever you want to name your postinit function
	local old_damage = inst.components.weapon.damage
	
	local function onproc(weapon, attacker, target)
		if attacker.components.leader and attacker.components.leader:IsBeingFollowedBy("<critter>") then
        	weapon.components.weapon:SetDamage(old_damage * <your multiplier>)
      	else
      		weapon.components.weapon:SetDamage(old_damage)
      	end
    end

  	if GLOBAL.TheWorld.ismastersim then
		inst.components.weapon:SetOnProc(onproc)
	end
end
AddPrefabPostInit("<weapon prefab>", PrefabPostInit)

 

By storing the original damage value in "old_damage", any other changes to the damage prior will also apply. It will all be forcibly multiplicative, but will all still be compatible with each other nonetheless.

The good thing about this set up is that it's a universal callback and is, as previously stated, pretty much identical to that of "onattack" with the exception that it's called before the actual attack is made. So now you have access to both before and after an attack, which only leads to more precise control of how weapons can interact with things when they attack. ;) 

Hope this helps! :) 

Edited by w00tyd00d
Link to comment
Share on other sites

@w00tyd00dthanks :)
Yes this is another workaround to be able to change the damage compatible to other mods.
I think it better fits to what you are doing (only change damage when attacking mob x). But in my case I want a "permanent" damamge modifier, in case critter is near, that's why I think changing the damageCalc function like Zupalex did, fits better (of course both work).

I already implemented Zupalex solution and also adopted it to change insulation and absorb values, works great.
So his method is kind of an overall solution for any changes (I mean that you use keys to identify your modifiers)
It's great, except in case the game or another mod sets a value to a fixed one... (eg. if a mod is setting absorb to 0 during the game, while there are absorb modifiers from your mod... this will mess up everything...) .. don't know a proper solution to prevent this... Does something like "getters and setters" in lua? Then we could solve this by writing a function that is called whenever someone does "absorb = 0", which will make sure all modifieres are handled correclty.
Alternativ solution is of course to not change an exisiting absorb value, but to change the Calc function and add your own absorb value to it, like Zupalex did for the damage modifier (cause changing the damagemultiplier value is too dangerous)

Anyway, I'm still unsure if 2 or more mods, that add these key-modifier mechanics to the same component, will be compatible...

Edited by Serpens
Link to comment
Share on other sites

@ZupaleX ?
I gave your code to other people who want to change damage, see here:
https://forums.kleientertainment.com/topic/83747-trying-to-add-damage-multiplier-to-hat-not-sure-how/?tab=comments#comment-970733

So will all mods work together without problems, if they all use this code? Or could there be conflicts regarding adjusting the combat component multiple times the same way?

Link to comment
Share on other sites

Sorry I was not around.

If everyone use it as is, you will end up with several mods adding the same function. Which is not a big deal it will just be overwritten by the last mod calling it, but it's just not very useful.

To answer your question, you can do the math yourself actually:

let's imagine mod A add it as well as mod B. The final function will effectively be doing the following when calling CalDamage

self.CalcDamage = function(self, target, weapon, multiplier)
      local dmg = function(self, target, weapon, multiplier)
      					local dmg = CalcDamageOld(self, target, weapon, multiplier)
      					local bonus = self.damagebonus or 0 --not affected by multipliers

      					return (dmg-bonus) * self:GetDamageModifier() + bonus
				end
      local bonus = self.damagebonus or 0 --not affected by multipliers

      return (dmg-bonus) * self:GetDamageModifier() + bonus
end

So first you will calculate damages the vanilla way. Then you retrieve the bonus, whatever it is at the moment of the calculation, and returns (dmg-bonus)*mod + bonus.

You then apply to this the next forumla which will eventually give you:

((dmg-bonus)*mod+bonus - bonus) * mod + bonus = (dmg-bonus)*mod^2 + bonus

so if N mods are doing it you will end up with a effective modifier of modifier^N. Not sure that's what you want.

I guess you could just check if the fields that you are adding already exists and if they do, then it means somebody else already took care of these modifiers before you and you can just skip it in your mod. Something like

AddComponentPostInit("combat", function(self)
	if self.attack_damage_modifiers == nil then
		RegisterNewCombatMembers(self)

		local CalcDamageOld = self.CalcDamage

		self.CalcDamage = function(self, target, weapon, multiplier)
			local dmg = CalcDamageOld(self, target, weapon, multiplier)
			local bonus = self.damagebonus or 0 --not affected by multipliers

			return (dmg-bonus) * self:GetDamageModifier() + bonus
		end
	end
end)

Like that you make sure the modification of the combat component is only applied once by the mod with the highest priority, and it will be ignored by the subsequent calls. However it still gives the ability to any mods to call these functions and use these modifiers tables.

This of course requires that all the mods implementing this type of solution comply to this check.

Edited by ZupaleX
Link to comment
Share on other sites

thank you, that was exactly what I was looking for and exactly the problem I ment with "incompatibility".

I edited my post here accordingly:
https://forums.kleientertainment.com/topic/83747-trying-to-add-damage-multiplier-to-hat-not-sure-how/?do=findComment&comment=970733

We should link it to everyone who wants to change damagemultiplier during the game. That way everyone will use this way and all mods will be compatible :)
 

Edited by Serpens
Link to comment
Share on other sites

found a small bug in the "GetDamageModifiers" function. It was:

local function GetDamageModifier(self)
  local mod = 1
  for k,v in pairs(self.attack_damage_modifiers) do
    mod = mod + v
  end
  return mod
end

but it should be multiplying, so :

local function GetDamageModifier(self)
  local mod = 1
  for k,v in pairs(self.attack_damage_modifiers) do
    mod = mod * v
  end
  return mod
end

edit:
and the self.attack_damage_modifiers are not saved when save/loading the game....
So we have to keep that in mind when working with it.
 

 

 

Edited by Serpens
Link to comment
Share on other sites

to discuss again about your archery mod:

I really like the mod, but I'm not sure about that new carver update...

I think it was very good that you were able to craft multiple arrows with one feather/twigs/flint.
And you knew exactly what arrow was good for which purpose.
And somehow I remember I was able to see the damage from each different arrow type, maybe with help of "show me" mod.

With the new carver it seems I only get one single arrow while using valueable ressources like 3 boneshards, or a lightninggoat horn or also feathers.
And you have no clue what the differences are?! I guess it doesnt matter anymore which feather colour you are using? But does the other components matter? And in which way? I don't know about special abilites AND and do not see the damage of the arrows. I cheated a yellow boneshard horn arrow and hit a bird. A lighting strike hit it, but the bird did not die and this very expensive arrow was gone (previously my character missed the target and the arrow had "discharged" in description, but when it hit the bird the lighting strike was still there, so maybe a bug?)

And are arrows still breakable the same way like before? So a specific chance to break? And how to make them less breakable?

The idea with the carver is great, but it lags much information and is not balanced I think.

Edited by Serpens
Link to comment
Share on other sites

18 hours ago, Serpens said:

With the new carver it seems I only get one single arrow while using valueable ressources like 3 boneshards, or a lightninggoat horn or also feathers.
And you have no clue what the differences are?!

Well the difference was supposed to be more valuable resources would make the arrow not break for more uses, like for example a lightning goat tip would have 10 durability then when it breaks you would get back a bone arrow with no tip which would then have its own durability & maybe could even reuse it by putting a tip on it again.

18 hours ago, Serpens said:

I guess it doesnt matter anymore which feather colour you are using?

Well in the future the feathers would slightly change arrow's performance like, red feather increases damage, blue feather increases range, yellow feather increases speed, ect.

18 hours ago, Serpens said:

And are arrows still breakable the same way like before? So a specific chance to break? And how to make them less breakable?

Yes they still break same way as before, the only way to make them break less I think is with use of this mod's potions http://steamcommunity.com/sharedfiles/filedetails/?id=496205036 I don't know if it's still compatible though

 

basically everything is all very wip :wilson_sneaky:

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...