Jump to content

Archery Mod: Discussion, Feedback and Thoughts


Recommended Posts

Hi everyone,

as you probably know don't know, I (code), @SuperDavid and @R.Remington (artwork) are preparing some updates for my Archery Mod which you can find on the workshop here

http://steamcommunity.com/sharedfiles/filedetails/?id=488009136

I will assume that you either used this mod already or that you visited the mod page linked above for the rest of this thread.

This update will include several major changes and it would be nice to have feedback from people who might have or might be in the future using this mod.

The first update will focus exclusively on the bow, the crossbow and musket will have their own update later.

For the first update, the crafting system will undergo a major overhaul. Only a few main components will be crafted from the classic tab from now on. These are:

     * The quiver

     * The bow, crossbow, musket, etc...

     * A new item family: the arrow carvers

The carvers will be the base object from which player will be able to craft arrows (and bolts in the future). It works basically like a crockpot:

Spoiler

3hyD4edBQKqadFaj9_O3Dg.png

(Yay at the quiver and the armor being displayed at the same time now)

This way allows for much more flexibility to craft arrows as this allows for multiple recipe for a single item. It also unclutter the crafting tab.

One of the first consequence also is that now arrows are defined by their 3 components: the feather, the shaft and the head. Unlike before, for instance a standard arrow was limited to a black feather with wood and flint. Now any feather can be used to craft an arrow with a flint head and a shaft made out of wood (or in the case of the screenshot, bone). As a result though arrows with yellow feather, wood shaft and flint head won't stack with red feather with wood shaft and flint head. The reason is that visually they will look different, but also eventually, for a future update, the feather will give different statistics to the arrow.

One of the first question we faced is: How do we deal with all of these new arrows which will fill the inventory slots.

The solution that we came up with is a "bundle" of arrow that would allow players to stack different types of arrow while keeping track of each single arrow in the bundle. When placing that bundle into the quiver, a random arrow from that bundle would be selected and shot.

Does that sound reasonable from a user point of view?

---------------------------------------------------------------------------------------------------------------------------------------------

Then unrelated with a feedback question I just wanted to share the fact that we will introduce a skin system for the archery items:

Spoiler

Meet the bow family

Meet the new bow family.

They all have different "achievement track" to unlock them, and while the progress made toward unlocking a skin is saved server side., once unlocked, the skins will be "linked to the player account" and will follow them no matter the server they are playing on.

The skin will be selected like any standard other DST official skin

Spoiler

DewH--JNReCq8IUL9mzIJQ.png

And finally here is a short sneak peek video. The animation/widgets used are just placeholder made/hacked by me in 15 minutes and will be changed by my 2 (too?) talented collaborators before the first update is pushed.

Spoiler

 

Thanks for reading :)

Edited by ZupaleX
Link to comment
Share on other sites

Since nobody complained thus far and the only comment is that it seems like a good idea, I guess I'll go ahead and implement it like that ^^.

I guess there will be more feedback once this is pushed to the actual mod and people don't have the choice but to use it :)

Link to comment
Share on other sites

So actually I thought about that.

The main difference between the old arrows and the new one is that you have more possibilities now. We actually did not create all the new arrows one by one. Instead I made 1 arrow build with 3 swappable symbols. On the art side then we just needed to create the different parts separately and then using AnimState:OverrideSymbol, all the arrows are created by script from these swappable parts.

The first update will make both version exists in parallel. The old arrows will be still craftable the old fashion way, I just edited their code to comply to the new animation system.

The second update will remove the old recipes for the arrows while keeping the prefabs.

The third one will completely remove the old arrow prefabs. People should have had time to get rid of their excess arrow until then.

The bow code changed but the prefab named remained the same. So all the old bow will just be upgraded to the new basic bow artwork and code.

 

I did not touch yet the crossbow and musket (except getting rid of the awful animation when recharging the musket and replacing it with the standard "dolongaction" animation). They will eventually undergo the same changes but will still remain compatible with old savegames.

Link to comment
Share on other sites

Hello again guys,

today I'd like to share something else entirely and ask again for an external opinion (hoping for more success than last time :D)

I worked today on porting the snakes from Shipwrecked along with the poison system (components, badge overlay, screen overlay, ...) to replace the current poison mechanics that the mod is using.

Here is the result of my day of fiddling with it

Spoiler

 

Now we are discussing about how to implement these snakes.

The current idea is to have the standard non poisonous one hiding in berry bushes, like the turkeys. They would go out when the player harvest their bush and go back in the nearest bush when day comes if the player did not kill it and is out of the aggro range.

The poisonous one would spawn from the snake den which could be found randomly in the antlion desert either in the open, or could be under flintless boulder which would be revealed when the player mines it.

The snakes could be found in caves as well when there is an earthquake, falling from the ceiling.

What do you guys think?

Edited by ZupaleX
Link to comment
Share on other sites

I think that i would love to use a poison system in my mod and wonder : is it possible to make it a kind of mod like the API skin so every player wanting to add poison enemies and poison remedies and stuff like this could use the same system instead of 10 custom system ?


I could totally understand if it's not possible/you don't want it but since i want it since a long time and it's too hard for me, i ask just in case.

 

About snakes : i would find it more fitting if they are in grass (especially in savanna), rather than bushes :

- this way it's different than gobblers

- veteran players still need grass, they don't use berry bushes that often

 

About poisonous snakes, i don't know what solution you plan to add against poison. But one thing i hated about shipwrecked was the fact that encountering a poisonous snake too early was a death sentence (no way to make antipoison, randomness of the poison gland drop, no way to have armor to prevent poisoning, and not a lot of healing item, since it's the beginning of the game...). So whatever you choose as a way to add it, make that the unavoidable ways take some time to applie. So for example, no poison snake for earthquake before first winter, or no poison snake for boulder mining until first winter again.

It's ok for the snake den in the antlion desert to be active all year because people have to choose to go in the desert, so they take the risk, it's a choice, it's ok.

Edited by Lumina
Link to comment
Share on other sites

Thanks for the thoughts that's very helpful.

What I did was just adding everything linked to the snakes, so all the prefabs they are dropping will be added to the game.

So the idea was to then have a recipe for the antivenom with 1 poison gland, 3 spider gland and 3 flower petals. That is subject to change if somebody has a better idea.

I understand your concern about encountering a poison snake too early. A solution could be to make them appear only later in the game (like no poison snake before the first spring?) while keeping the den active from the start in the antlion desert. The drop rate for poison glands could also be increased? A new item could be introduced that would not cure the poison but slows it down so the player would not necessarily die even if the poison is not cured after 3 days. That could be relatively easy to make so even if encountered early game it's not immediate death but at least it's annoying enough?

The snake from the grass in the savana is a good idea I like it. Maybe standard non poisonous snake den could be found in the savana as well?

 

About making an API out of it:

I considered this idea. I just did not do it like that (yet) for 3 reasons:

-> Since I started working on it just yesterday, it's still in early test phase and it's easier to debug if I have everything at the same place

-> I don't like having my mods depend on other download from the workshop.

-> Since some folks are preparing a Shipwrecked port, it seemed like a lot of efforts for something which might not be so useful eventually.

But I will still seriously consider doing so :) 

Edited by ZupaleX
Link to comment
Share on other sites

I agree to your and Luminas ideas , great :)

I don't have more ideas, but I also think it would be better to make the poison stuff an API mod.
Also because maybe some players do not want archery, but like the snakes+poison. And of course other modders could use the poison stuff for new mobs, as Lumina said.

And archery mod could also work without the poison, but "if posion mod is enabled, you will also have poisined arrows and so on"

Edited by Serpens
Link to comment
Share on other sites

It is very painful to make sure that there is no bugs in a system like the one you described so if I make it an API, it will be a requirement to have it to be able to use the archery. I did that once, enabling options only if another mod is on as well, and if I agree it's not complicated to do, it's just tedious work to make sure the proper conditions are set everywhere :)

Link to comment
Share on other sites

What you could do is make it being base stuff in Archery mod, and make it available as an API for modder. So either they have to have the API or the Archery mod, but your mod works fine alone.

Of course, it require to maintain both mods so it could be annoying so it's up to you.

 

1 hour ago, ZupaleX said:

A solution could be to make them appear only later in the game (like no poison snake before the first spring?) while keeping the den active from the start in the antlion desert.

Yes, winter or spring for wild spawn, from the start in the antlion desert, depending of how hard it's to aquire anti venom.

 

1 hour ago, ZupaleX said:

A new item could be introduced that would not cure the poison but slows it down so the player would not necessarily die even if the poison is not cured after 3 days. That could be relatively easy to make so even if encountered early game it's not immediate death but at least it's annoying enough?

Yes, it's also a great way to show the different options for players to add items against poison. Also maybe a new piece of gear protecting for poison (but it could be harder for the graphic part).

I don't have idea at the moment for the recipe, unfortunately...

1 hour ago, ZupaleX said:

 

The snake from the grass in the savana is a good idea I like it. Maybe standard non poisonous snake den could be found in the savana as well?

It's a good idea, it could make savana feel a little less empty.

Link to comment
Share on other sites

I guess with the "required items" option when uploading mods on the workshop it's not such a big deal to make the archery dependent on a poison API.

I will start working on it as soon as all the functionality are working as intended.

Link to comment
Share on other sites

1 hour ago, ZupaleX said:

I guess with the "required items" option when uploading mods on the workshop it's not such a big deal to make the archery dependent on a poison API.

I will start working on it as soon as all the functionality are working as intended.

As far as I know the "required items" on steamm is just visual. So the only effect is, that you see it marked "required" at your mod page.
You can still start the mod without the other mod and get crash (or other bugs) if you miss a required mod.

What is the problem with checking if another mod is active or not?
I'm not 100% familiar with that, most modders use the "knownmodindex" or similar named. But the steam user "star" wrote a more complex way to check. So I think at least the code from star should be working fine? (I think eg. found in his "show me" mod)

So if you make two mods (archery and poison) it definitely would be better to make them not dependant on each other.

 

stars code:

Spoiler

local _G = GLOBAL

local GetGlobal=function(gname,default)
	local res=_G.rawget(_G,gname)
	if res == nil and default ~= nil then
		_G.rawset(_G,gname,default)
		return default
	end
	return res
end

--Locals (Add compatibility with any other mineable mods).
local mods = GetGlobal("mods",{})

--Detecting enabled mods
local mod_names	 --названия всех модов (чтобы не дергать джвижок)
local mod_names_nover --названия модов с обрезанной версией (если смысловая часть достаточно длинная)
mod_names = {}
mod_names_nover = {}
local function GetAllModNames()
	if not (_G.KnownModIndex and _G.KnownModIndex.savedata and _G.KnownModIndex.savedata.known_mods
		and _G.ModManager and _G.ModManager.enabledmods)
	then
		return
	end
	local folders = {} --ассоциативный массив включенных модов (по папкам)
	for _,v in ipairs(_G.ModManager.enabledmods) do
		folders[v]=true
	end
	for folder, mod in pairs(_G.KnownModIndex.savedata.known_mods) do
		local name = mod.modinfo.name
		if name then
			mod_names[name]=folders[folder] and true or false
			--print("NEW_MOD: "..name.." "..tostring(mod_names[name]))
			local s=string.match(name,"^(.-)([0-9%._ ]+)$")
			if s then
				mod_names_nover[s]=name --обрезаем номер версии с конца
				--вместо true сохраняем полное имя мода (чтобы идентифицировать его в системе)
			else
				mod_names_nover[name]=name
			end
		end
	end
end
GetAllModNames()
mods.mod_names = mod_names
mods.mod_names_nover = mod_names_nover


local function SearchForModsByName()
	if mods.active_mods_by_name then
		return --Уже проинициализировано. Либо полная несовместимость.
	end
	mods.active_mods_by_name = {}
	if not (_G.KnownModIndex and _G.KnownModIndex.savedata and _G.KnownModIndex.savedata.known_mods) then
		print("ERROR COMMON LIB: Can't find KnownModIndex!")
		return
	end
	for name,mod in pairs(_G.KnownModIndex.savedata.known_mods) do
		if (mod.enabled or mod.temp_enabled or _G.KnownModIndex:IsModForceEnabled(name)) --Мод активен
			and not mod.temp_disabled --И не отключен
		then
			local real_name = mod.modinfo.name
			if real_name == nil then
				print("SHOW_ME ERROR: real_name of a mod is nil,",tostring(name))
				--TODO: error if TUNING.STAR_DEBUG 
			else
				mods.active_mods_by_name[real_name] = true
			end
		end
	end
end	
SearchForModsByName()
	
local is_HealthInfo = mods.active_mods_by_name["Health Info"] --Check it to decide, is there a reason to show hp in description.

 

Edited by Serpens
Link to comment
Share on other sites

The problem is not checking if it is enabled. The problem is then put conditions everywhere where there is an item involved that should be active only if mod X is active. And when you have a a lot of files and a few thousands of line of codes, that is painful to maintain.

Link to comment
Share on other sites

52 minutes ago, ZupaleX said:

The problem is not checking if it is enabled. The problem is then put conditions everywhere where there is an item involved that should be active only if mod X is active. And when you have a a lot of files and a few thousands of line of codes, that is painful to maintain.

ok, depends on how my files would be poison related.

Link to comment
Share on other sites

So I extracted everything related to the poison mechanics from my archery mod and put it in a separate mod.

This mod does all the AddPrefabPostInit, AddComponentPostInit and AddClassPostConstruct necessary to display the poison badge overlay, the poison hurt overlay and add the required components for all of this to work properly. It also add the snakes and all the loots coming with them.

Now in term of "API" the mod exposes the following functions:

* A function to make an entity poisonable and set different parameters for it including (but not exclusive to):

  • if the poison bubble fxs should be played and how (loop, only on poison pulse, the symbol the bubble should follow and the offset relative to this symbol, ...)
  • The damage penalty the entity will suffer because they are poisoned. This is a damage reduction on their attack, not how much they take per poison tick
  • An attack period penalty due to poison
  • a speed movement penalty due to poison
  • a hunger burn modifier due to poison

* A function to make an entity inflict poison damages with the parameters you would expect for such a function.

Anything else you'd like to see?

 

EDIT: the only thing I did not put in is the poisoned idle animation for the player because I find it very ugly but if you think I should put it in I can.

Edited by ZupaleX
Link to comment
Share on other sites

The sanity is implemented as well, I forgot to list it :p

I tried to stick as close as possible to the original SW fnction which makes an entity poisonable. But to allow deeper modification, I added a function on top of it which is

SetEntityPoisonProperty(propertie, value)

to modify additional things like the poison resistance of an entity by doing for instance assuming you are in a character prefab function (master only part)

MakePoisonableEntity(inst, nil, nil, "player", 0, 0, 1)
SetEntityPoisonProperty("poison_damage_scale", 2)

If somebody wants to test it internally to see how it works, if it is not too clunky, functionality are unclear/broken/missing please let me know.

Link to comment
Share on other sites

Some questions :

 

Is it possible to make item able to poison ? (like a food, poisoning when eating)

Could you change the graphic effect, like, if i'm making a poison draining sanity super fast, purple bubble/smoke instead of green bubble ?

Also, what happen if you have a kind of poison and another should apply ? (Like, one with big sanity drain, and one classic ?)

Sorry if the questions have obvious answer !

I'm not the best to help you test, my coding is too bad for this.

Edited by Lumina
Link to comment
Share on other sites

It would be possible to make food poisoning but it is not implemented by the base SW poison system. I could add it fairly easily though.

The graphics effect could be changed without too much effort. I guess I could make it so it's even easier than what it is currently.

There is only one "type" of poison. I added myself the notion of poison strength which plays a role on how much health is removed per tick. Then the stat about the sanity drain and hunger burn modifier are actually not linked to the entity poisoning but to the entity getting poisoned. I guess in the same way I added a poison strength for the damage, I can add modifiers for the sanity drains and hunger burn modifier.

 

Also do you think I should keep a mod only with the poisoning system as a pure API and keep the snakes themselves and everything going with it in another separate mod? Because yesterday I started to add all the items linked with the snake and it went a bit out of control. I ended up adding the machetes, the vine bush, the hackable component, the obsidiantool component (since the machete has an obsidian version), some items linked to the vines so it is actually useful, the obsidian workbench...

Link to comment
Share on other sites

15 hours ago, ZupaleX said:

 

Also do you think I should keep a mod only with the poisoning system as a pure API and keep the snakes themselves and everything going with it in another separate mod?

Yes, it's probably a better option to keep the API as neutral as possible.

Link to comment
Share on other sites

And please make sure to stay compatible to other mods.

Especially the damage modifier is tricky. You are an expert modder, so I'm sure add it correctly.
The last time I checked the game itself has no function to change damagemultiplier savely (like it is possible for speed).
So what is your workaround to make sure your mod is not reverting any changes done by other mods?
And especially wolfgang is setting damagemultipler like every second to the new value, depending on his hunger...

Link to comment
Share on other sites

I am the first one to complain when mods are breaking the compatibility with other mods so rest assured I do everything I can to make it the best possible (to the extent of my skills).

 

Here is the combat implementation if you are interested in checking it. It should not affect any other mod modifying this component (if done properly as well...)

 

Spoiler

--*****************************************************************************************************************************************--
------------------------------------------------- Combat Component Adjustments --------------------------------------------------------------
--*****************************************************************************************************************************************--

local function AddDamageModifier(self, key, mod)
  self.attack_damage_modifiers[key] = mod
end

local function RemoveDamageModifier(self, key)
  self.attack_damage_modifiers[key] = nil
end

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

local function AddPeriodModifier(self, key, mod)
  self.attack_period_modifiers[key] = { mod = mod, effective = self.min_attack_period * mod }
  self:SetAttackPeriod(self.min_attack_period * (1+mod))
end

local function RemovePeriodModifier(self, key)
  self:SetAttackPeriod(self.min_attack_period - self.attack_period_modifiers[key].effective)
  self.attack_period_modifiers[key] = nil
end

local function GetPeriodModifier(self)
  local mod = 0
  for k,v in pairs(self.attack_period_modifiers) do
    mod = mod + v
  end
  return mod
end

local function RegisterNewCombatMembers(self)
  self.poisonstrength = 1
  
  self.poisonous = nil
  self.gasattack = nil

  self.attack_damage_modifiers = {} -- % modifiers on self:CalcDamage()
  self.attack_period_modifiers = {} -- % modifiers on self.min_attack_period

  self.AddDamageModifier = AddDamageModifier
  self.RemoveDamageModifier = RemoveDamageModifier
  self.GetDamageModifier = GetDamageModifier

  self.AddPeriodModifier = AddPeriodModifier
  self.RemovePeriodModifier = RemovePeriodModifier
  self.GetPeriodModifier = GetPeriodModifier
end

local function GetIsAttackPoison(self, attacker)
  local poisonAttack = false 
  local poisonGasAttack = false 

  if self.inst:HasTag("poisonable") and attacker then 
    if (attacker.components.combat and attacker.components.combat.poisonous) or 
    ((attacker.components.poisonable and attacker.components.poisonable:IsPoisoned() and attacker.components.poisonable.transfer_poison_on_attack) 
      and (attacker.components.combat and not attacker.components.combat:GetWeapon())) then

      poisonAttack = true 

      if (attacker.components.combat and attacker.components.combat.poisonous and attacker.components.combat.gasattack) then 
        poisonGasAttack = true 
      end 
    end 
  end   

  return poisonAttack, poisonGasAttack
end

AddComponentPostInit("combat", function(self)
    RegisterNewCombatMembers(self)

    local GetAttackedOld = self.GetAttacked

    self.GetAttacked = function(self, attacker, damage, weapon, stimuli)
      local poisonAttack, poisonGasAttack = GetIsAttackPoison(self, attacker)

      if poisonGasAttack and self.inst.components.poisonable then 
        self.inst.components.poisonable:Poison(true)
        return
      end

      local notblocked = GetAttackedOld(self, attacker, damage, weapon, stimuli)

      if notblocked and attacker and poisonAttack and self.inst.components and self.inst.components.poisonable then
        self.inst.components.poisonable:Poison()
      end
    end

    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
)

 

 

Edited by ZupaleX
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...