|
@ -81,7 +81,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
* general/
|
||||
* [mobs_animal][] ([MIT][lic.mobs_animal]) -- version: [52889c7 Git][ver.mobs_animal] *2018-06-27* ([patched][patch.mobs_animal])
|
||||
* [monsters_aggressive][] (see individual mods for licensing) -- version: [89a8187 Git][ver.monsters_aggressive] *2017-08-30*
|
||||
* [mobs_goblins][] ([CC BY-SA][lic.mobs_goblins]) -- version: [0ac7755 Git][ver.mobs_goblins] *2017-11-16*
|
||||
* [goblins][] ([CC BY-SA][lic.goblins]) -- version: [eb9055b Git][ver.goblins] *2021-03-21*
|
||||
* [monsters_passive][] (see individual mods for licensing) -- version: [b07fe19 Git][ver.monsters_passive] *2017-08-09*
|
||||
* [painting][] (???) -- version [8961849 Git][ver.painting] *2016-05-05*
|
||||
* [pipeworks][] ([LGPL][lic.lgpl3.0]) -- version: [2021-02-19][ver.pipeworks]
|
||||
|
@ -246,7 +246,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
[minetest_game]: https://github.com/minetest/minetest_game
|
||||
[mob-engine]: https://github.com/minetest-mods/mob-engine
|
||||
[mobs_animal]: https://github.com/tenplus1/mobs_animal
|
||||
[mobs_goblins]: https://github.com/FreeLikeGNU/mobs_goblins
|
||||
[goblins]: https://forum.minetest.net/viewtopic.php?t=13004
|
||||
[mobs_redo]: https://forum.minetest.net/viewtopic.php?t=9917
|
||||
[monsters_aggressive]: https://github.com/AntumMT/mp-monsters_aggressive
|
||||
[monsters_passive]: https://github.com/AntumMT/mp-monsters_passive
|
||||
|
@ -338,7 +338,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
[lic.mesecons]: mods/modpacks/mesecons/COPYING.txt
|
||||
[lic.mob-engine]: mods/modpacks/mob-engine/LICENSE
|
||||
[lic.mobs_animal]: mods/mobiles/general/mobs_animal/license.txt
|
||||
[lic.mobs_goblins]: mods/mobiles/monsters_aggressive/goblins/README.md
|
||||
[lic.goblins]: mods/mobiles/monsters_aggressive/goblins/README.md
|
||||
[lic.mobs_redo]: mods/mobiles/engine/mobs_redo/license.txt
|
||||
[lic.moreblocks]: mods/buildings/moreblocks/LICENSE.md
|
||||
[lic.moreores]: mods/materials/moreores/LICENSE.md
|
||||
|
@ -450,7 +450,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
[ver.minetest_game]: https://github.com/minetest/minetest_game/tree/5.4.1
|
||||
[ver.mob-engine]: https://github.com/minetest-mods/mob-engine/tree/c2bedc3
|
||||
[ver.mobs_animal]: https://github.com/tenplus1/mobs_animal/tree/52889c7
|
||||
[ver.mobs_goblins]: https://github.com/FreeLikeGNU/mobs_goblins/tree/0ac7755
|
||||
[ver.goblins]: https://github.com/FreeLikeGNU/goblins/tree/eb9055b
|
||||
[ver.mobs_redo]: https://notabug.org/TenPlus1/mobs_redo/src/f6e16a550330cf6a641753c03ebe331682294939
|
||||
[ver.monsters_aggressive]: https://github.com/AntumMT/mp-monsters_aggressive/tree/89a8187
|
||||
[ver.monsters_passive]: https://github.com/AntumMT/mp-monsters_passive/tree/b07fe19
|
||||
|
|
|
@ -1,38 +1,101 @@
|
|||
# [goblins] Goblins (Mobs Redo addon) [mod] for Minetest
|
||||
|
||||
* forum: https://forum.minetest.net/viewtopic.php?f=9&t=13004
|
||||
* code :https://github.com/FreeLikeGNU/goblins
|
||||
* Minetest Content DB: https://content.minetest.net/packages/FreeLikeGNU/goblins/
|
||||
|
||||
# mobs_goblins Goblins mod for Minetest
|
||||
## by Francisco "FreeLikeGNU" Athens
|
||||
https://forum.minetest.net/viewtopic.php?f=9&t=13004
|
||||
https://github.com/FreeLikeGNU/mobs_goblins
|
||||
This mod adds several Goblins (and Goblin Dogs) to Minetest that should spawn near ore deposits or lairs underground.
|
||||
|
||||
* code based on MOBS-MOD by PilzAdam, KrupnovPavel, Zeg9, TenPlus1
|
||||
https://forum.minetest.net/viewtopic.php?f=9&t=9917
|
||||
* Goblins dig caves, destroy torches, create lairs, set traps, cultivate mushrooms and some are aggressive.
|
||||
* Gobdogs will roam caves, bury bones and other items in soft terrain, eat meats. Some Gobdogs are aggressive!
|
||||
* Basic trading with Goblins - the more you trade with a goblin, the more likely you will get things in return!
|
||||
* Goblins have a territorial framework for location based interactions, if you trade with more Goblins of a territory
|
||||
your trades will be easier!
|
||||
* Harming goblins will negatively affect your trade with all gobins in a territory!
|
||||
* If you brandish weapons (including axes) around a goblin it may decide to attack!
|
||||
* Goblins and Gobdogs will defend each other. You can have them defend other mobs by simply
|
||||
adding to:
|
||||
`on_spawn = function(self)`
|
||||
the following:
|
||||
`self.groups = {"goblin_friend", "gobdog_friend"}`
|
||||
in your own mobs definition!
|
||||
* There are many settings now accessible from the minetest menu -> "settings" tab -> "all settings" -> "mods" -> "goblins" list!
|
||||
these can also be defined in the settingtypes.txt
|
||||
* Goblin and Gobdog spawning is now configured from goblins_spawning.lua (at least until there is a way to easily change these with the setting menu :P )
|
||||
* A basic and optional (enabled in minetest setting menu) HUD is available
|
||||
* tested with Minetest 5.2 and 5.30(dev)
|
||||
|
||||
This mod adds several Goblins to Minetest that should spawn near ore deposits or lairs underground.
|
||||
## Required Mods:
|
||||
* Mobs Redo by TenPlus1 API as of version 20200516: to run
|
||||
* https://forum.minetest.net/viewtopic.php?f=9&t=9917
|
||||
* Mobs Redo git repository https://notabug.org/TenPlus1/mobs_redo
|
||||
|
||||
* Goblins dig caves, destroy torches, create lairs, set traps and some are aggressive.
|
||||
## Optional Mods:
|
||||
* Ambience Lite by TenPlus1 API
|
||||
* https://notabug.org/TenPlus1/ambience
|
||||
|
||||
License of Media Files:
|
||||
---------------------------------------
|
||||
* Hunger NG by Linuxdirk
|
||||
* https://forum.minetest.net/viewtopic.php?t=19664
|
||||
* https://gitlab.com/4w/hunger_ng
|
||||
|
||||
* Bonemeal by TenPlus1
|
||||
* https://forum.minetest.net/viewtopic.php?t=16446
|
||||
* https://notabug.org/TenPlus1/bonemeal
|
||||
|
||||
## Licenses of Source Media Files:
|
||||
* goblins_goblin.b3d and goblins_goblin.blend
|
||||
Copyright 2015 by Francisco "FreeLikeGNU" Athens Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
http://creativecommons.org/licenses/by-sa/3.0/
|
||||
* Copyright 2015 by Francisco "FreeLikeGNU" Athens Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
* http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
* above meshes based on character from minetest_game
|
||||
by MirceaKitsune (WTFPL)
|
||||
https://github.com/minetest/minetest_game/blob/master/mods/default/README.txt#L71
|
||||
* by MirceaKitsune (WTFPL)
|
||||
* https://github.com/minetest/minetest_game/blob/master/mods/default/README.txt#L71
|
||||
|
||||
* goblins_goblins*.png files and goblins_goblin.xcf files
|
||||
Copyright 2015 by Francisco "FreeLikeGNU" Athens Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
http://creativecommons.org/licenses/by-sa/3.0/
|
||||
* Copyright 2015,2020 by Francisco "FreeLikeGNU" Athens Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
* http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
* Sound files by:
|
||||
* artisticdude http://opengameart.org/content/goblins-sound-pack CC0-license
|
||||
* Ogrebane http://opengameart.org/content/monster-sound-pack-volume-1 CC0-license
|
||||
* spookymodem http://opengameart.org/content/mining-pick CC-BY 3.0
|
||||
* goblins_goblin_dog.b3d and goblins_goblin_dog*.blend
|
||||
* Copyright 2016,2020 by Francisco "FreeLikeGNU" Athens Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
* http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
* goblins_goblin_dog*.png files and goblins_goblin_dog*_.xcf files
|
||||
* Copyright 2015 by Francisco "FreeLikeGNU" Athens Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
* http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
## Additional source and content credits:
|
||||
* goblin mushrooms from "flowers" mod source code:
|
||||
* Originally by Ironzorg (MIT) and VanessaE (MIT)
|
||||
* Various Minetest developers and contributors (MIT)
|
||||
|
||||
* mushrooms.xcf Copyright Francisco Athens (CC BY-SA 3.0) 2020
|
||||
* goblins_mushroom_brown.png, goblins_mushroom_brown2.png goblins_mushroom_brown3.png goblins_mushroom_brown4.png Copyright Francisco Athens (CC BY-SA 3.0) 2020
|
||||
|
||||
## Sound files by:
|
||||
* artisticdude http://opengameart.org/content/goblins-sound-pack (CC0-license)
|
||||
* Ogrebane http://opengameart.org/content/monster-sound-pack-volume-1 (CC0-license)
|
||||
* goblins_ambient_underground: 232685__julius-galla__atmosphere-cave-loop (CC-BY-SA)
|
||||
* https://freesound.org/people/julius_galla/sounds/232685/
|
||||
* goblins_goblin_trap: LittleRobotSoundFactory (CC-BY-SA)
|
||||
* https://freesound.org/people/LittleRobotSoundFactory/
|
||||
* goblins_goblin_breathing: spookymodem
|
||||
* https://freesound.org/people/spookymodem/ (CC-0)
|
||||
* goblins_goblin_dog_ sounds:
|
||||
* delphidebrain Jazz the Dog Howl & Bark (CC-BY-SA)
|
||||
* https://freesound.org/people/delphidebrain/sounds/236027/
|
||||
* Glitchedtones Dog Shih Tzu Growling 06.wav (CC-BY-SA)
|
||||
* https://freesound.org/people/Glitchedtones/sounds/372533/
|
||||
|
||||
* Super thanks to duane-r for his work on nasty traps and tunneling https://github.com/duane-r
|
||||
|
||||
* Thanks to Napiophelios for the goblin king skin
|
||||
https://forum.minetest.net/viewtopic.php?f=9&t=13004#p186921
|
||||
goblins_goblin_king.png
|
||||
License: Creative Commons CC-BY-SA-3.0 SummerFeilds TP
|
||||
* --Thanks to duane-r for his work on making traps nastier!: https://github.com/duane-r/mobs_goblins/blob/work/goblin_traps.lua
|
||||
* https://forum.minetest.net/viewtopic.php?f=9&t=13004#p186921
|
||||
* goblins_goblin_king.png
|
||||
* License: Creative Commons (CC-BY-SA-3.0 SummerFeilds TP
|
||||
|
||||
Thanks to orbea for adding Hunger NG and Bonemeal mod support and bugfixes!
|
||||
* https://github.com/orbea
|
||||
Thanks to TenPlus1 for keeping the Mobs_Redo going!
|
||||
Thanks to rubenwardy for awesome help and the Minetest ContentDB
|
||||
Thanks to everyone in the Minetest forums and IRC for just being great!
|
||||
GET MINETEST: https://www.minetest.net/
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
local function variance(min,max)
|
||||
local target = math.random(min,max) / 100
|
||||
--print(target)
|
||||
return target
|
||||
end
|
||||
|
||||
local gob_name_parts = goblins.gob_name_parts
|
||||
local goblins_spawning = goblins.spawning
|
||||
goblins.gobdog_types = {
|
||||
gobdog = {
|
||||
owner_loyal = true,
|
||||
attack_npcs = false,
|
||||
attack_monsters = false,
|
||||
group_attack = true,
|
||||
attack_players = true,
|
||||
},
|
||||
gobdog_aggro = {
|
||||
description ="Dire Gobdog",
|
||||
lore = "Dire Gobdogs are sensitive to light and are very territorial",
|
||||
type = "monster",
|
||||
group_attack = true,
|
||||
owner_loyal = true,
|
||||
attack_npcs = false,
|
||||
attack_monsters = false,
|
||||
attack_players = true,
|
||||
|
||||
spawning = goblins_spawning.gobdog_aggro
|
||||
},
|
||||
}
|
||||
-------------
|
||||
-- Gobdog Template
|
||||
------------
|
||||
goblins.gobdog_template = {
|
||||
description ="Gobdog",
|
||||
lore = "Gobdogs are not canids but goblins that have mutated somehow, fortunately they do not share the hunger and size of the mythical werewolf.",
|
||||
type = "npc",
|
||||
attack_type = "dogfight",
|
||||
group_attack = true,
|
||||
reach = 2,
|
||||
damage = 1,
|
||||
hp_min = 2,
|
||||
hp_max = 5,
|
||||
armor = 100,
|
||||
stepheight = 1.2,
|
||||
walk_velocity = 2,
|
||||
run_velocity = 4,
|
||||
jump = true,
|
||||
jump_height = 6,
|
||||
pushable = true,
|
||||
knock_back = true,
|
||||
view_range = 15,
|
||||
water_damage = 0,
|
||||
lava_damage = 5,
|
||||
light_damage = 0,
|
||||
fear_height = 4,
|
||||
floats = 1,
|
||||
--glow = 1,
|
||||
pathfinding = 1,
|
||||
stay_near = {
|
||||
"group:water", 20,
|
||||
"group:sand", 20,
|
||||
"group:soil", 20,
|
||||
"default:mossycobble", 10,
|
||||
"group:meat" ,2,
|
||||
"goblins:goblins_goblin_bone_meaty"},
|
||||
collisionbox = {-0.45, -0.01, -0.45, 0.45, 0.85, 0.45},
|
||||
visual = "mesh",
|
||||
mesh = "goblins_goblin_dog.b3d",
|
||||
textures = {
|
||||
{"goblins_goblin_dog.png"},
|
||||
},
|
||||
makes_footstep_sound = true,
|
||||
sounds = {
|
||||
random = "goblins_goblin_dog_ambient_cave",
|
||||
war_cry = "goblins_goblin_dog_war_cry_cave",
|
||||
attack = "goblins_goblin_dog_attack_cave",
|
||||
damage = "goblins_goblin_dog_damage_cave",
|
||||
death = "goblins_goblin_dog_death_cave",
|
||||
replace = "goblins_goblin_dog_replace_cave",gain = 0.8,
|
||||
},
|
||||
follow = {
|
||||
"goblins:goblins_goblin_bone","goblins:goblins_goblin_bone_meaty","group:meat"
|
||||
},
|
||||
drops = {
|
||||
{name = "goblins:goblins_goblin_bone", chance = 1, min = 1, max = 3},
|
||||
},
|
||||
animation = {
|
||||
speed_normal = 60,
|
||||
stand_start = 0,
|
||||
stand_end = 60,
|
||||
walk_start = 70,
|
||||
walk_end = 90,
|
||||
run_start = 130,
|
||||
run_end = 140,
|
||||
run_speed =30,
|
||||
jump_start = 160,
|
||||
jump_end = 190,
|
||||
jump_loop = true,
|
||||
jump_speed = 30,
|
||||
punch_start = 130,
|
||||
punch_end = 140,
|
||||
punch_speed = 30,
|
||||
die_start = 140,
|
||||
die_stop = 145,
|
||||
die_speed = 30,
|
||||
die_loop = false,
|
||||
},
|
||||
|
||||
on_spawn = function(self)
|
||||
minetest.sound_play("goblins_goblin_dog_war_cry_cave", {
|
||||
object = self.object,
|
||||
gain = .5,
|
||||
max_hear_distance =30
|
||||
})
|
||||
self.groups = {"gobdog", "goblin"}
|
||||
self.groups_defend = {"goblin","gobdog","gobdog_friend"}
|
||||
if not self.secret_name then
|
||||
local name_rules = {"list_a", "list_opt"}
|
||||
self.secret_name = goblins.generate_name(gob_name_parts, name_rules)
|
||||
end
|
||||
--print (dump(self.secret_name))
|
||||
local pos = vector.round(self.object:get_pos())
|
||||
if not pos then return end
|
||||
if not self.secret_territory then
|
||||
local territory = {goblins.territory(pos)}
|
||||
self.secret_territory = {name = territory[1], vol = territory[2]}
|
||||
--print(dump(self.secret_territory.name).." secret_territory assigned")
|
||||
else
|
||||
--print(dump(self.secret_territory.name).." secret_territory already assigned")
|
||||
end
|
||||
local color_var = "#"..math.random(10,50)..math.random(10,50)..math.random(10,50)
|
||||
--print("COLOR_VAR: "..color_var)
|
||||
self.object:set_texture_mod("^[colorize:"..color_var..":80")
|
||||
|
||||
if not self.size then
|
||||
local s_mod = variance(1,20)
|
||||
self.size = {x = (variance(90,100) - s_mod), y = (variance(80,110) - s_mod), z = (variance(90,100) - s_mod)}
|
||||
end
|
||||
|
||||
local self_properties = self.object:get_properties()
|
||||
self_properties.visual_size = self.size
|
||||
self.object:set_properties(self_properties)
|
||||
goblins.announce_spawn(self)
|
||||
end,
|
||||
|
||||
on_rightclick = function(self, clicker)
|
||||
if mobs:feed_tame(self, clicker, 4, true, true) then return end
|
||||
if mobs:protect(self, clicker) then return end
|
||||
if mobs:capture_mob(self, clicker, 0, 5, 50, false, nil) then return end
|
||||
end,
|
||||
---dog behaviors or not...
|
||||
do_custom = function(self)
|
||||
goblins.goblin_dog_behaviors(self)
|
||||
end,
|
||||
|
||||
do_punch = function(self,hitter)
|
||||
local pname = hitter:get_player_name()
|
||||
local relations = goblins.relations(self, pname)
|
||||
if not relations.aggro then
|
||||
goblins.relations(self, pname, {aggro = 0})
|
||||
relations = goblins.relations(self, pname)
|
||||
end
|
||||
--print(self.secret_name.." relations on click:\n"..dump(self.relations).."\n")
|
||||
if self.relations[pname].aggro then
|
||||
local adj = (self.relations[pname].aggro + 1) * 1.5
|
||||
self.relations[pname].aggro = math.floor(adj)
|
||||
goblins.relations(self, pname, {aggro = self.relations[pname].aggro} )
|
||||
end
|
||||
end,
|
||||
|
||||
spawning = goblins_spawning.gobdog
|
||||
}
|
||||
|
||||
mobs:alias_mob("goblins:goblins_goblin_dog", "goblins:goblin_gobdog")
|
||||
mobs:alias_mob("goblins:goblin_goblin_dog", "goblins:goblin_gobdog")
|
||||
|
||||
mobs:alias_mob("goblins:goblins_goblin_dog_aggro", "goblins:goblin_gobdog_aggro")
|
||||
mobs:alias_mob("goblins:goblin_goblin_dog_aggro", "goblins:goblin_gobdog_aggro")
|
|
@ -0,0 +1,819 @@
|
|||
|
||||
local debug_goblins_attack = minetest.settings:get_bool("debug_goblins_attack") or false
|
||||
local debug_goblins_find = minetest.settings:get_bool("debug_goblins_find") or false
|
||||
local debug_goblins_replace = minetest.settings:get_bool("debug_goblins_replace") or false
|
||||
local debug_goblins_replace2 = minetest.settings:get_bool("debug_goblins_replace2") or false
|
||||
local debug_goblins_search = minetest.settings:get_bool("debug_goblins_search") or false
|
||||
local debug_goblins_tunneling = minetest.settings:get_bool("debug_goblins_tunneling") or false
|
||||
local debug_goblins_trade = minetest.settings:get_bool("debug_goblins_trade") or false
|
||||
|
||||
--@trade_shrewdness increases trade difficulty
|
||||
local goblins_trade_shrewdness = tonumber(minetest.settings:get("goblins_trade_shrewdness")) or 20
|
||||
|
||||
--@aggro_on_wield will goblins attack when a weapon is wielded?
|
||||
local goblins_aggro_on_wield = minetest.settings:get_bool("goblins_aggro_on_wield") ~= false
|
||||
--@goblins_defend_groups will goblins and gobdogs defend other mobs?
|
||||
local goblins_defend_groups = minetest.settings:get_bool("goblins_defend_groups") ~= false
|
||||
|
||||
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
||||
local goblins_node_protect_strict = minetest.settings:get_bool("goblins_node_protect_strict") ~= false
|
||||
local peaceful_only = minetest.settings:get_bool("only_peaceful_mobs")
|
||||
|
||||
local S = minetest.get_translator("goblins")
|
||||
|
||||
local gob_name_parts = goblins.gob_name_parts
|
||||
|
||||
local function strip_escapes(input)
|
||||
goblins.strip_escapes(input)
|
||||
end
|
||||
|
||||
local function print_s(input)
|
||||
print(goblins.strip_escapes(input))
|
||||
end
|
||||
|
||||
function goblins.mixitup(pos)
|
||||
pos.y = pos.y + math.random()
|
||||
pos.x = pos.x + math.random()
|
||||
pos.x = pos.x - math.random()
|
||||
pos.z = pos.z + math.random()
|
||||
pos.z = pos.z - math.random()
|
||||
return pos
|
||||
end
|
||||
|
||||
local function match_item_list(item, list)
|
||||
for k,v in pairs(list) do
|
||||
local found = string.find(item, v)
|
||||
return found
|
||||
end
|
||||
end
|
||||
|
||||
local function match_only_list(item, list)
|
||||
for k,v in pairs(list) do
|
||||
if item == v then
|
||||
return v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Goblins will become aggro at range due to
|
||||
-- wielded weapon, player aggression, defending defined mob groups
|
||||
-- some attack code reused from Mobs Redo by TenPlus1
|
||||
function goblins.attack(self, target, type)
|
||||
if self.state == "runaway"
|
||||
or self.state == "attack"
|
||||
or self:day_docile()
|
||||
or peaceful_only == true
|
||||
then
|
||||
--print_s(S("player not considered"))
|
||||
return
|
||||
end
|
||||
|
||||
local pos = vector.round(self.object:get_pos())
|
||||
if pos then
|
||||
local s = self.object:get_pos()
|
||||
local objs = minetest.get_objects_inside_radius(s, self.view_range)
|
||||
local aggro_wielded = {}
|
||||
if goblins_aggro_on_wield then
|
||||
aggro_wielded = self.aggro_wielded
|
||||
end
|
||||
local defend_groups = goblins_defend_groups
|
||||
--print_s(S(dump(aggro_wielded)))
|
||||
-- remove entities we aren't interested in
|
||||
for n = 1, #objs do
|
||||
local ent = objs[n]:get_luaentity()
|
||||
-- are we a player?
|
||||
if objs[n]:is_player() then
|
||||
local pname = objs[n]:get_player_name()
|
||||
local relations_self = {}
|
||||
local relations = {}
|
||||
local relations_adj = 0
|
||||
--do we know this player?
|
||||
local relations_self = goblins.relations(self, pname)
|
||||
if not relations_self.trade then goblins.relations(self, pname,{trade = 0}) end
|
||||
if not relations_self.aggro then goblins.relations(self, pname,{aggro = 0}) end
|
||||
|
||||
--tally the territorial scores
|
||||
relations.aggro = goblins.relations_territory(self, pname, "aggro")
|
||||
relations.trade = goblins.relations_territory(self, pname, "trade")
|
||||
if debug_goblins_attack then
|
||||
print_s(S("@1 of @2: ", self.secret_name, self.secret_territory.name))
|
||||
print_s(S("mob relations = @1",dump(goblins.relations(self, pname))))
|
||||
print_s(S("comparing territory trade @1 and aggro @2",dump(relations.trade),dump(relations.aggro)))
|
||||
end
|
||||
|
||||
if relations.trade >= relations.aggro then
|
||||
relations_adj = relations.trade - relations.aggro
|
||||
end
|
||||
if debug_goblins_attack then print_s(S("relations = @1",dump(relations))) end
|
||||
if mobs.invis[pname]
|
||||
or self.owner == pname then
|
||||
local name = ""
|
||||
else
|
||||
local player = objs[n]
|
||||
local name = "player"
|
||||
end
|
||||
-- if player invisible or mob not setup to attack then remove from list
|
||||
local wielded = objs[n]:get_wielded_item():to_string()
|
||||
--print(self.secret_name.." is loyal to " ..self.owner)
|
||||
if debug_goblins_attack then print_s( S("player has @1 in hand",dump(objs[n]:get_wielded_item():to_string())))end
|
||||
if self.attack_players == false
|
||||
or relations_adj >= 100
|
||||
or not self.owner == pname
|
||||
--or not self.tamed
|
||||
or mobs.invis[pname]
|
||||
or self.specific_attack == "player" then
|
||||
if debug_goblins_attack then print_s(S("found exempt player with score of @1 holding @2",relations_adj,dump(objs[n]:get_wielded_item():to_string()))) end
|
||||
objs[n] = nil
|
||||
--print("- pla", n)
|
||||
else
|
||||
if debug_goblins_attack then print_s(S("attackable player, @1 holding @2",pname,wielded)) end
|
||||
--lets check if our friends in a fight with the player!
|
||||
for n = 1, #objs do
|
||||
local ent_other = objs[n]:get_luaentity()
|
||||
if defend_groups and ent_other and ent_other.groups and self.groups_defend then
|
||||
for k,v in pairs(self.groups_defend) do
|
||||
if match_only_list(v, ent_other.groups) and
|
||||
ent_other.state == "attack" and
|
||||
ent_other.attack:is_player() and
|
||||
ent_other.attack:get_player_name() == pname then
|
||||
local xname = ent_other.attack:get_player_name()
|
||||
if debug_goblins_attack then print_s( S(" ****Defending @1 from @2!",v,xname)) end
|
||||
minetest.sound_play("goblins_goblin_war_cry", {
|
||||
pos = pos,
|
||||
gain = 1.0,
|
||||
max_hear_distance = self.sounds.distance or 10
|
||||
})
|
||||
self:set_animation("run")
|
||||
self:set_velocity(self.run_velocity)
|
||||
self.state = "attack"
|
||||
self.attack = ent_other.attack
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if aggro_wielded and match_item_list(wielded, aggro_wielded)
|
||||
then
|
||||
if debug_goblins_attack then print_s(S("*** aggro triggered by @1 at @2 !! ***",wielded,minetest.pos_to_string(pos))) end
|
||||
minetest.sound_play("goblins_goblin_war_cry", {
|
||||
pos = pos,
|
||||
gain = 1.0,
|
||||
max_hear_distance = self.sounds.distance or 10
|
||||
})
|
||||
self:set_animation("run")
|
||||
self:set_velocity(self.run_velocity)
|
||||
self.state = "attack"
|
||||
self.attack = (objs[n])
|
||||
end
|
||||
end
|
||||
end --end of player eval
|
||||
--what else do we care about?
|
||||
--group_attack mobs nearby
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Drops a special personlized item
|
||||
function goblins.special_gifts(self, pname, drop_chance, max_drops)
|
||||
if pname then
|
||||
if self.drops then
|
||||
if not drop_chance then drop_chance = 1000 end
|
||||
if not max_drops then max_drops = 1 end
|
||||
local rares = {}
|
||||
for k,v in pairs(self.drops) do
|
||||
--print_s(dump(v.name).." and "..dump(v.chance))
|
||||
if v.chance >= drop_chance then
|
||||
table.insert(rares,v.name)
|
||||
end
|
||||
end
|
||||
if #rares > 0 then
|
||||
--print_s("rares = "..dump(rares))
|
||||
local pos = self.object:get_pos()
|
||||
if pos then
|
||||
pos.y = pos.y + 0.5
|
||||
goblins.mixitup(pos)
|
||||
if #rares > max_drops then
|
||||
rares = rares[math.random(max_drops, #rares)]
|
||||
if type(rares) ~= table then rares = {rares} end --
|
||||
end
|
||||
for k,v in pairs(rares) do
|
||||
minetest.sound_play("goblins_goblin_cackle", {
|
||||
pos = pos,
|
||||
gain = 1.0,
|
||||
max_hear_distance = self.sounds.distance or 10
|
||||
})
|
||||
local item_wear = math.random(5000,10000)
|
||||
local stack = ItemStack({name = v, wear = item_wear })
|
||||
local org_desc = minetest.registered_items[v].description
|
||||
local meta = stack:get_meta()
|
||||
local tool_adj = goblins.generate_name(goblins.words_desc, {"tool_adj"})
|
||||
-- special thanks here to rubenwardy for showing me how translation works!
|
||||
meta:set_string(
|
||||
"description", S("@1's @2 @3", self.secret_name, tool_adj, org_desc)
|
||||
)
|
||||
local obj = minetest.add_item(pos, stack)
|
||||
minetest.chat_send_player(
|
||||
pname,S("@1 drops @2",self.secret_name, meta:get_string("description"))
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---grab the score for a territory
|
||||
--@rel_names are a table of relations to reference
|
||||
function goblins.get_scores(self,player_name,rel_names)
|
||||
local t_scores = {}
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
if not player then return end
|
||||
local meta = player:get_meta()
|
||||
local pdata = {}
|
||||
--local pdata[self.secret_territory] = {}
|
||||
for k,v in pairs(rel_names) do
|
||||
t_scores[v] = goblins.relations_territory(self, player_name, v)
|
||||
pdata[k] = v
|
||||
end
|
||||
--print_s(S("t_scores = @1",dump(t_scores)))
|
||||
--write player data
|
||||
meta:set_string(self.secret_territory.name, minetest.serialize(t_scores))
|
||||
--print("*** player meta = "..meta:get_string(self.secret_territory.name))
|
||||
meta:set_string("territory_current", self.secret_territory.name)
|
||||
if self.secret_name_told and self.secret_name_told[player_name] then
|
||||
meta:set_string("goblin_current", self.secret_name)
|
||||
print("*** player meta = "..meta:get_string("goblin_current"))
|
||||
else
|
||||
meta:set_string("goblin_current", "unknown goblin")
|
||||
end
|
||||
|
||||
goblins.update_hud(player)
|
||||
return t_scores
|
||||
end
|
||||
|
||||
--calculate tables of scores and get results
|
||||
local function score_calc(add, sub)
|
||||
local adds = 0
|
||||
local subs = 0
|
||||
local score = 0
|
||||
if add then
|
||||
for k,v in pairs(add) do
|
||||
adds = v + adds
|
||||
end
|
||||
end
|
||||
if sub then
|
||||
for k,v in pairs(sub) do
|
||||
subs = v + subs
|
||||
end
|
||||
end
|
||||
if adds >= subs then
|
||||
score = adds - subs
|
||||
return score
|
||||
else score = 0
|
||||
end
|
||||
return score
|
||||
end
|
||||
-- prepare trade score for giving a gift
|
||||
local function trade_score(self, player_name)
|
||||
local add = {}
|
||||
local sub = {}
|
||||
local rel_names = {"trade", "aggro"}
|
||||
local rel_scores = goblins.get_scores(self,player_name,rel_names)
|
||||
add[1] = rel_scores.trade
|
||||
sub[1] = rel_scores.aggro
|
||||
local result = score_calc(add, sub)
|
||||
--print_s(S("calculated score = @1",dump(result)))
|
||||
return result
|
||||
end
|
||||
--- You can give a gift, they *may* give something(s) in return, thats Goblin trading
|
||||
function goblins.give_gift(self,clicker)
|
||||
--if mobs:feed_tame(self, clicker, 14, false, false) then
|
||||
local item = clicker:get_wielded_item()
|
||||
local pname = clicker:get_player_name()
|
||||
local gift_accepted = nil
|
||||
local gift_declined = nil
|
||||
|
||||
local name_told = goblins.secret_name(self, pname)
|
||||
local territory_told = goblins.secret_territory(self, pname)
|
||||
local trade_shrewdness = goblins_trade_shrewdness
|
||||
--establish trade if its not set
|
||||
if not self.relations[pname] then
|
||||
goblins.relations(self, pname, {trade = 0})
|
||||
end
|
||||
if debug_goblins_trade then print_s(dump(goblins.relations(self, pname))) end
|
||||
local srp_trade = self.relations[pname].trade
|
||||
local gift = item:get_name()
|
||||
local gift_description = item:get_definition().description
|
||||
if debug_goblins_trade then print_s("you offer: " ..dump(gift)) end
|
||||
for k,v in pairs(self.follow) do
|
||||
if v == gift then
|
||||
local gift_value = k or 5 --higher number is less wanted gift, otherwise 10
|
||||
gift_accepted = true
|
||||
if debug_goblins_trade then print_s(S("@1 accepts @2 (@3)",self.name,dump(gift),k)) end
|
||||
--increase trade rating on gifting - first item in follow list is worth more
|
||||
srp_trade = srp_trade + math.ceil(5/k)
|
||||
if gift == self.follow[1] then
|
||||
srp_trade = srp_trade + 4
|
||||
minetest.chat_send_player(pname,"Yessss! " .. gift_description.."!")
|
||||
end
|
||||
goblins.relations(self, pname,{trade = srp_trade})
|
||||
if debug_goblins_trade then print_s("this goblins trade rating is now = " ..dump(srp_trade)) end
|
||||
local gr_trade = trade_score(self, pname)
|
||||
if debug_goblins_trade then print_s("Goblin adjusted (trade - aggro) relations for territory is = "..dump(gr_trade)) end
|
||||
if not minetest.settings:get_bool("creative_mode") then
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
end
|
||||
---appease an attacking goblin
|
||||
if self.state == "attack" and self.attack == clicker then
|
||||
if (self.relations[pname].aggro * 2) < self.relations[pname].trade then
|
||||
self.state = "stand"
|
||||
self:set_velocity(0)
|
||||
self:set_animation("stand")
|
||||
self.attack = nil
|
||||
self.v_start = false
|
||||
self.timer = 0
|
||||
self.blinktimer = 0
|
||||
self.path.way = nil
|
||||
end
|
||||
end
|
||||
--print_s(dump(self.object:get_luaentity()).. " at " ..dump(self.object:get_pos()).. " takes: " ..dump(item:get_name()))
|
||||
if self.drops then
|
||||
if debug_goblins_trade then
|
||||
print_s("you may get some of "..dump(#self.drops).. " things such as: ")
|
||||
for _,v in pairs(self.drops) do
|
||||
print_s(dump(v.name).. " with a base drop chance of 1 in " ..dump(v.chance))
|
||||
end
|
||||
end
|
||||
-- we can make some mobs extra stingy despite trade relations
|
||||
if not self.shrewdness then self.shrewdness = 1 end
|
||||
local pos = self.object:get_pos()
|
||||
if pos then
|
||||
pos.y = pos.y + 0.5
|
||||
for _,v in pairs(self.drops) do
|
||||
--@d_chance takes all the factors of trade into account for each item in drop list
|
||||
local d_chance = 0
|
||||
d_chance = ((gift_value + v.chance) * (self.shrewdness + trade_shrewdness)) / (gr_trade + 1)
|
||||
--print(v.name.." d_chance = " ..d_chance)
|
||||
--more likely to get something really rare , less likely to get something common
|
||||
if gift == self.follow[1] then d_chance = self.shrewdness + trade_shrewdness end
|
||||
d_chance = math.ceil(d_chance)
|
||||
if math.random(d_chance) == 1 then
|
||||
if debug_goblins_trade == true then
|
||||
print_s(S("\n @1 dropped by @2 at an adjusted chance of 1 in @3", dump(v.name),dump(self.name),dump(d_chance)))
|
||||
end
|
||||
minetest.sound_play("goblins_goblin_cackle", {
|
||||
pos = pos,
|
||||
gain = 0.2,
|
||||
max_hear_distance = self.sounds.distance or 10
|
||||
})
|
||||
--let it go already!
|
||||
goblins.mixitup(pos)
|
||||
minetest.add_item(pos, {
|
||||
name = v.name
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
gift_accepted = true
|
||||
if name_told and territory_told then
|
||||
minetest.chat_send_player(pname,S("@1 of @2 takes your @3!",self.secret_name,self.secret_territory.name,gift_description))
|
||||
elseif name_told then
|
||||
minetest.chat_send_player(pname,S("@1 takes your @2!",self.secret_name,gift_description))
|
||||
else
|
||||
minetest.chat_send_player(pname,S("Goblin takes your @1!", gift_description))
|
||||
end
|
||||
return gift_accepted --acception of gift complete
|
||||
else
|
||||
if debug_goblins_trade == true then print_s("You did not offer " .. dump(string.split(v,":")[2]) ) end
|
||||
end
|
||||
end
|
||||
local pos = self.object:get_pos()
|
||||
if pos then
|
||||
minetest.sound_play("goblins_goblin_damage", {
|
||||
pos = pos,
|
||||
gain = 0.2,
|
||||
max_hear_distance = self.sounds.distance or 10
|
||||
})
|
||||
end
|
||||
if name_told and territory_told then
|
||||
minetest.chat_send_player(
|
||||
pname,S("@1 of @2 does not want your @3",
|
||||
self.secret_name,self.secret_territory.name,gift_description))
|
||||
elseif name_told then
|
||||
minetest.chat_send_player(pname,S("@1 does not want your @2",self.secret_name,gift_description))
|
||||
else
|
||||
minetest.chat_send_player(pname,S("Goblin does not want your @1",gift_description))
|
||||
end
|
||||
gift_declined = true
|
||||
end
|
||||
|
||||
--- Replaces nodes with many params.
|
||||
function goblins.search_replace(
|
||||
self,
|
||||
search_rate,
|
||||
search_rate_above,
|
||||
search_rate_below,
|
||||
search_offset,
|
||||
search_offset_above,
|
||||
search_offset_below,
|
||||
replace_rate,
|
||||
replace_what,
|
||||
replace_with,
|
||||
replace_rate_secondary,
|
||||
replace_with_secondary,
|
||||
decorate, --this is for placing attached nodes like goblin mushrooms and torches
|
||||
debug_me,
|
||||
tools) -- {primary, secondary} based on index# of self.goblin_tools
|
||||
local pos = self.object:get_pos()
|
||||
if pos and mobs_griefing and not minetest.is_protected(pos, "") and math.random(1, search_rate) == 1 then
|
||||
-- look for nodes
|
||||
local pos = self.object:get_pos()
|
||||
local pos1 = self.object:get_pos()
|
||||
local pos2 = self.object:get_pos()
|
||||
|
||||
--local pos = vector.round(self.object:get_pos()) --will have to investigate these further
|
||||
--local pos1 = vector.round(self.object:get_pos())
|
||||
--local pos2 = vector.round(self.object:get_pos())
|
||||
local tool_set = {}
|
||||
if tools then
|
||||
tool_set = tools
|
||||
end
|
||||
|
||||
-- if we are looking, will we look below and by how much?
|
||||
if pos1 and math.random(1, search_rate_below) == 1 then
|
||||
pos1.y = pos1.y - search_offset_below
|
||||
end
|
||||
|
||||
-- if we are looking, will we look above and by how much?
|
||||
if pos2 and math.random(1, search_rate_above) == 1 then
|
||||
pos2.y = pos2.y + search_offset_above
|
||||
end
|
||||
|
||||
pos1.x = pos1.x - search_offset
|
||||
pos1.z = pos1.z - search_offset
|
||||
pos2.x = pos2.x + search_offset
|
||||
pos2.z = pos2.z + search_offset
|
||||
|
||||
if debug_goblins_search and debug_me then
|
||||
print (self.name:split(":")[2] .. " at\n "
|
||||
.. minetest.pos_to_string(pos) .. " is searching between\n "
|
||||
.. minetest.pos_to_string(pos1) .. " and\n "
|
||||
.. minetest.pos_to_string(pos2))
|
||||
end
|
||||
|
||||
local nodelist = minetest.find_nodes_in_area(pos1, pos2, replace_what)
|
||||
if #nodelist > 0 then
|
||||
if debug_goblins_find and debug_me then
|
||||
print_s(#nodelist.." nodes found by " .. self.name:split(":")[2]..":")
|
||||
for k,v in pairs(nodelist) do print_s(minetest.get_node(v).name:split(":")[2].. " found.") end
|
||||
end
|
||||
for key,value in pairs(nodelist) do
|
||||
value = vector.round(value)
|
||||
-- ok we see some nodes around us, are we going to replace them?
|
||||
if minetest.is_protected(value, "") and goblins_node_protect_strict then break end
|
||||
if math.random(1, replace_rate) == 1 then
|
||||
local air_value = nil
|
||||
if replace_rate_secondary and
|
||||
math.random(1, replace_rate_secondary) == 1 then
|
||||
if decorate then
|
||||
value = minetest.find_node_near(value, 1, "air")
|
||||
end
|
||||
if value ~= nil then
|
||||
-- print("decorating with "..replace_with_secondary..minetest.pos_to_string(value))
|
||||
if tools and self.goblin_tools and type(self.goblin_tools) == "table" then
|
||||
local replace = tools[2]
|
||||
goblins.tool_attach(self,self.goblin_tools[replace])
|
||||
--print("changing tool: "..self.goblin_tools[replace])
|
||||
end
|
||||
self:set_velocity(0)
|
||||
self:set_animation("punch")
|
||||
if decorate then
|
||||
minetest.set_node(value, {name = replace_with_secondary})
|
||||
else
|
||||
minetest.set_node(value, {name = replace_with_secondary})
|
||||
end
|
||||
end
|
||||
if debug_goblins_replace2 and debug_me then
|
||||
print_s(replace_with_secondary.." secondary node placed by " .. self.name:split(":")[2])
|
||||
end
|
||||
else
|
||||
if decorate then
|
||||
value = minetest.find_node_near(value, 1, "air")
|
||||
end
|
||||
if value ~= nil then
|
||||
if tools and self.goblin_tools and type(self.goblin_tools) == "table" then
|
||||
local replace = tools[1]
|
||||
goblins.tool_attach(self,self.goblin_tools[replace])
|
||||
--print("changing tool: "..self.goblin_tools[replace])
|
||||
end
|
||||
-- print("decorating with "..replace_with..minetest.pos_to_string(value))
|
||||
self:set_velocity(0)
|
||||
self:set_animation("punch")
|
||||
if decorate then
|
||||
minetest.set_node(value, {name = replace_with})
|
||||
else
|
||||
minetest.set_node(value, {name = replace_with})
|
||||
end
|
||||
end
|
||||
if debug_goblins_replace and debug_me then
|
||||
print_s(replace_with.." placed by " .. self.name:split(":")[2])
|
||||
end
|
||||
end
|
||||
minetest.sound_play(self.sounds.replace, {
|
||||
object = self.object, gain = self.sounds.gain,
|
||||
max_hear_distance = self.sounds.distance
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
"He destroys everything diggable in his path. It's too much trouble
|
||||
to fudge around with particulars. Besides, I don't want them to
|
||||
mine for me."
|
||||
--From the tome __Of Goblinkind__ by duane-r
|
||||
|
||||
"The domain of stone is the Goblins home,
|
||||
by metals might one thwart them from invasion."
|
||||
--Epithet from __The Luanacy of Goblins__ by Persont Bachslachdi
|
||||
--]]
|
||||
|
||||
--the following is built from duane-r's goblin tunnel digging:
|
||||
local diggable_nodes = {"group:stone", "group:sand", "group:soil", "group:cracky", "group:crumbly"}
|
||||
-- This translates yaw into vectors.
|
||||
local cardinals = {{x=0,y=0,z=0.75}, {x=-0.75,y=0,z=0}, {x=0,y=0,z=-0.75}, {x=0.75,y=0,z=0}}
|
||||
----------
|
||||
-- Goblins Tunneling.
|
||||
---------
|
||||
-- @type are available for fine-tuning.
|
||||
function goblins.tunneling(self, type)
|
||||
--
|
||||
if type == nil then
|
||||
type = "digger"
|
||||
end
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
if pos and mobs_griefing and not minetest.is_protected(pos, "") then
|
||||
if self.state == "tunnel" then
|
||||
self:set_animation("walk")
|
||||
self:set_velocity(self.walk_velocity)
|
||||
-- Yaw is stored as one of the four cardinal directions.
|
||||
if not self.digging_dir then
|
||||
self.digging_dir = math.random(0,3)
|
||||
end
|
||||
|
||||
-- Turn him roughly in the right direction.
|
||||
-- self.object:setyaw(self.digging_dir * math.pi * 0.5 + math.random() * 0.5 - 0.25)
|
||||
self.object:setyaw(self.digging_dir * math.pi * 0.5)
|
||||
|
||||
-- Get a pair of coordinates that should cover what's in front of him.
|
||||
local p = vector.add(pos, cardinals[self.digging_dir+1])
|
||||
-- p.y = p.y - 1 -- What's this about?
|
||||
local p1 = vector.add(p, .1)
|
||||
local p2 = vector.add(p, 1.5)
|
||||
|
||||
-- Get any diggable nodes in that area.
|
||||
local np_list = minetest.find_nodes_in_area(p1, p2, diggable_nodes)
|
||||
if #np_list > 0 then
|
||||
-- Dig it.
|
||||
--print(" NP_LIST: ".. dump(np_list))
|
||||
for _, np in pairs(np_list) do
|
||||
if minetest.is_protected(np, "") and goblins_node_protect_strict then break end
|
||||
local np_info = minetest.get_node(np)
|
||||
--print(" np_name: "..np_info.name)
|
||||
if np_info.name ~= "default:mossycobble" and np_info.name ~= "default:chest" then
|
||||
self:set_animation("punch")
|
||||
minetest.remove_node(np)
|
||||
minetest.sound_play(self.sounds.replace, {
|
||||
object = self.object, gain = self.sounds.gain,
|
||||
max_hear_distance = self.sounds.distance
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if math.random() < 0.2 then
|
||||
local d = {-1,1}
|
||||
self.digging_dir = (self.digging_dir + d[math.random(2)]) % 4
|
||||
end
|
||||
self.state = "walk"
|
||||
self:set_animation("walk")
|
||||
self:set_velocity(self.walk_velocity)
|
||||
|
||||
elseif self.state == "room" then -- Dig a room.
|
||||
--[[first make sure player is not near by! (not quite ready yet)
|
||||
goblins.must_hide = function()
|
||||
end --]]
|
||||
if not self.room_radius then
|
||||
self.room_radius = 1
|
||||
end
|
||||
|
||||
self:set_velocity(0)
|
||||
self.state = "stand"
|
||||
self:set_animation("stand")
|
||||
|
||||
-- Work from the inside, out.
|
||||
for r = 1,self.room_radius do
|
||||
-- Get a pair of coordinates that form a room.
|
||||
local p1 = vector.add(pos, -r)
|
||||
local p2 = vector.add(pos, r)
|
||||
-- But not below him.
|
||||
p1.y = pos.y
|
||||
|
||||
local np_list = minetest.find_nodes_in_area(p1, p2, diggable_nodes)
|
||||
|
||||
--FLG prefers a smaller room with a rougher look for goblin warrens. Maybe this should be a setting for users preference?
|
||||
if r >= self.room_radius and #np_list == 0 then
|
||||
--self.room_radius = math.random(1,2) + math.random(0,1)
|
||||
self.room_radius = math.random(1,1.5) + math.random(0,0.5)
|
||||
-- self.state = "stand"
|
||||
-- self:set_velocity(0)
|
||||
-- self:set_animation("stand")
|
||||
break
|
||||
end
|
||||
|
||||
if #np_list > 0 then -- dig it
|
||||
if goblins_node_protect_strict then break end
|
||||
self:set_animation("punch")
|
||||
minetest.remove_node(np_list[math.random(#np_list)])
|
||||
minetest.sound_play(self.sounds.replace, {
|
||||
object = self.object, gain = self.sounds.gain,
|
||||
max_hear_distance = self.sounds.distance
|
||||
})
|
||||
break
|
||||
end
|
||||
self.state = "walk"
|
||||
self:set_animation("walk")
|
||||
self:set_velocity(self.walk_velocity)
|
||||
end
|
||||
end
|
||||
---the following values should be vars for settings...
|
||||
--if we are standing, maybe make a tunnel or
|
||||
--if we are tunneling, maybe make a room or
|
||||
--if we are tunneling stand or maybe just end this function
|
||||
--
|
||||
if self.state == "stand" and math.random() < 0.1 then
|
||||
self.state = "tunnel"
|
||||
if debug_goblins_tunneling then print_s("goblineer is now tunneling") end
|
||||
elseif self.state == "tunnel" and math.random() < 0.1 then
|
||||
self.state = "room"
|
||||
if debug_goblins_tunneling then print_s("goblineer is now making a room") end
|
||||
elseif self.state == "tunnel" and math.random() < 0.1 then
|
||||
self.state = "stand"
|
||||
if debug_goblins_tunneling then print_s(dump(vector.round(self.object:get_pos())).. "goblineer is thinking...") end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function goblins.danger_dig(self,freq,depth)
|
||||
local gpos = self.object:get_pos()
|
||||
if gpos then
|
||||
local pos = vector.round(gpos)
|
||||
local lol = minetest.get_node_light(pos) or 0
|
||||
local freq = freq or 0.1
|
||||
local depth = depth or 1
|
||||
local target = table.copy(pos)
|
||||
target.y = target.y - depth
|
||||
|
||||
if self.light_damage_min and
|
||||
lol >= self.light_damage_min and
|
||||
mobs_griefing and
|
||||
not minetest.is_protected(target, "") and
|
||||
math.random() <= freq and
|
||||
minetest.get_node(target).name ~="air" then
|
||||
local target_node = minetest.get_node(target)
|
||||
|
||||
if self.state ~= "stand" then self.state = "stand" end
|
||||
|
||||
--find a pick among goblin tools if we can
|
||||
if self.goblin_tools and type(self.goblin_tools) == "table" then
|
||||
local tool = match_item_list("pick",self.goblin_tools)
|
||||
if tool then
|
||||
goblins.tool_attach(self,self.goblin_tools[tool])
|
||||
--print("changing tool: "..self.goblin_tools[replace])
|
||||
end
|
||||
end
|
||||
|
||||
self:set_velocity(0)
|
||||
self:set_animation("punch")
|
||||
minetest.remove_node(target)
|
||||
local node_above = vector.round(self.object:get_pos())
|
||||
node_above.y = node_above.y + 2
|
||||
local nb_node1 = vector.round(self.object:get_pos())
|
||||
local nb_node2 = vector.round(self.object:get_pos())
|
||||
nb_node1.y = node_above.y
|
||||
nb_node2.y = node_above.y
|
||||
nb_node1.x = nb_node1.x - 1
|
||||
nb_node1.z = nb_node1.z - 1
|
||||
nb_node2.x = nb_node1.x + 1
|
||||
nb_node2.z = nb_node1.z + 1
|
||||
local air_nodes = minetest.find_nodes_in_area(nb_node1,nb_node2, "air")
|
||||
--print(#nodes)
|
||||
if #air_nodes == 1 then
|
||||
minetest.set_node(node_above, {name = target_node.name})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
function goblins.goblin_dog_behaviors(self)
|
||||
local pos = self.object:get_pos()
|
||||
if pos then
|
||||
if math.random() < 0.1 then
|
||||
goblins.attack(self)
|
||||
--print("looking for a reason to fight")
|
||||
end
|
||||
if mobs_griefing and not minetest.is_protected(pos, "") then
|
||||
if math.random() < 0.5 then
|
||||
--consume meaty bones"
|
||||
goblins.search_replace(
|
||||
self,
|
||||
100, --search_rate
|
||||
100000, --search_rate_above
|
||||
100000, --search_rate_below
|
||||
1, --search_offset
|
||||
1, --search_offset_above
|
||||
1, --search_offset_below
|
||||
5, --replace_rate
|
||||
{"group:meat","group:food_meat","group:food_meat_raw"}, --replace_what
|
||||
"goblins:goblins_goblin_bone", --replace_with
|
||||
10, --replace_rate_secondary
|
||||
"air", --replace_with_secondary --very hungry
|
||||
nil, --decorate
|
||||
false --debug_me if debugging also enabled in behaviors.lua
|
||||
)
|
||||
elseif math.random() < 0.5 then
|
||||
--consume dry bones"
|
||||
goblins.search_replace(
|
||||
self,
|
||||
100, --search_rate
|
||||
100000, --search_rate_above
|
||||
100000, --search_rate_below
|
||||
1, --search_offset
|
||||
1, --search_offset_above
|
||||
1, --search_offset_below
|
||||
5, --replace_rate
|
||||
"goblins:goblins_goblin_bone", --replace_what
|
||||
"air", --replace_with
|
||||
nil, --replace_rate_secondary
|
||||
nil, --replace_with_secondary
|
||||
nil, --decorate
|
||||
false--debug_me if debugging also enabled in behaviors.lua
|
||||
)
|
||||
elseif math.random() < 0.8 then
|
||||
--dig and maybe bury bones if theres suitable terrain around
|
||||
goblins.search_replace(
|
||||
self,
|
||||
100, --search_rate
|
||||
100000, --search_rate_above
|
||||
100, --search_rate_below
|
||||
1, --search_offset
|
||||
1, --search_offset_above
|
||||
2, --search_offset_below
|
||||
10, --replace_rate
|
||||
{"group:soil",
|
||||
"group:sand",
|
||||
"default:gravel"}, --replace_what
|
||||
"goblins:dirt_with_bone",
|
||||
2, --replace_rate_secondary
|
||||
"default:dirt", --replace_with_secondary
|
||||
nil, --decorate
|
||||
false --debug_me if debugging also enabled in behaviors.lua
|
||||
)
|
||||
else
|
||||
--or maybe bury something more useful
|
||||
goblins.search_replace(
|
||||
self,
|
||||
100, --search_rate
|
||||
100000, --search_rate_above
|
||||
100, --search_rate_below
|
||||
1, --search_offset
|
||||
1, --search_offset_above
|
||||
2, --search_offset_below
|
||||
10, --replace_rate
|
||||
{"group:soil",
|
||||
"group:sand",
|
||||
"default:gravel"}, --replace_what
|
||||
"goblins:dirt_with_stuff",
|
||||
2, --replace_rate_secondary
|
||||
"default:dirt", --replace_with_secondary
|
||||
nil, --decorate
|
||||
false --debug_me if debugging also enabled in behaviors.lua
|
||||
)
|
||||
end
|
||||
end
|
||||
--[[not quite ready yet...
|
||||
if math.random() < 0.01 then
|
||||
goblins.do_taunt_at(self)
|
||||
print_s("are " ..dump(self.name).. " barking?" )
|
||||
end
|
||||
--]]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
* Update 2021/03/21 Various object checks have been added to eliminate crashes.
|
||||
* Update 2020/07/12 Goblins dig to safety! Also, random tool selection weight fixes.
|
||||
* Update 2020/07/06 added moss node and removed glow from cobblemoss node for better visuals
|
||||
more variations for goblin tools and appropriate tools/nodes are chosen for tasks
|
||||
* Update 2020/06/29 fixed a crash with protection enabled (such as with minecarts). Thanks to rusty-snake for reporting this!
|
||||
* Update 2020/06/28 fixed a crashing bug in hud code, attached tools to goblins, new goblin animation and texture mods
|
||||
* Update 2020/06/18 Optional HUD (enable in Minetest options menu)
|
||||
* Update 2020/06/11 Custom Goblins and Gobdogs can be defined in goblins_custom.lua
|
||||
attacking goblins can now be appeased through trade
|
||||
* Update 2020/06/07 Goblin and Gobdog spawning is now configured from goblins_spawning.lua (at least until there is a way to easily change these with the setting menu :P )
|
||||
* Update 2020/06/06 There are many settings now accessible from the minetest menu -> "settings" tab -> "all settings" -> "mods" -> "goblins" list! these can also be defined in the settingtypes.txt
|
||||
* Update 2020/06/04 Mobs now defend each other (and will defend other mobs with a simple modification to those mobs)
|
||||
* Update 2020/05/21 Aggro on player wielding a weapon. Trade affected by player aggression.
|
||||
* Update 2020/05/09 Territorial enhancements:
|
||||
The more goblins you trade with from a territory the better and more frequent drops you receive from trading!
|
||||
Multiplayer works with territory and trade relations, each player has their own relations with goblins and territories.
|
||||
Internationalization support begun to allow for translations
|
||||
Personalized drops from goblins when you have learned their name and territory
|
||||
* Update 2020/05/05 Goblins have territories defined by chunk!
|
||||
Optional HungerNG and Bonemeal mod support thanks to orbea!
|
||||
* Update 2020/05/01 Goblins have names!
|
||||
* Update 2020/04/21: Gobdogs added!
|
||||
* Update 2020/04/18: Implemented tunneling function from duane-r's goblins. Behavioral functions now get their own file.
|
||||
* Update 2020/04/17: Added TenPlus1 [url=https://notabug.org/TenPlus1/ambience]ambience[/url] support as optional dependency. Weaker goblins are more timid around player.
|
||||
more variety in sounds added.
|
||||
* Update 2020/04/13: Goblin Fungiler added.
|
||||
* Update 2020/04/11: Goblins get some updates and fixes. Should work with Minetest 5.30 (dev)[/spoiler]
|
|
@ -1 +1,4 @@
|
|||
default
|
||||
mobs
|
||||
ambience?
|
||||
hunger_ng?
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
local S = minetest.get_translator("goblins")
|
||||
|
||||
-- Create new goblins here (or override existing ones).
|
||||
-- This example just overrides the existing Cobble, feel to remove it
|
||||
--[[
|
||||
goblins.gob_types.cobble = {
|
||||
description = S("Cobblemoss Goblin"),
|
||||
lore = S("Cobbler crumbles walls infusing them with moss to collect moisture for a fetid, mushroom friendly habitat."),
|
||||
damage = 1,
|
||||
hp_min = 5,
|
||||
hp_max = 10,
|
||||
sounds = {
|
||||
random = {"goblins_goblin_breathing",gain = 0.5},
|
||||
war_cry = "goblins_goblin_war_cry",
|
||||
attack = "goblins_goblin_attack",
|
||||
damage = "goblins_goblin_damage",
|
||||
death = "goblins_goblin_death",
|
||||
replace = "default_place_node",gain = 0.8,
|
||||
distance = 15
|
||||
},
|
||||
textures = {
|
||||
{"goblins_goblin_cobble1.png"},
|
||||
{"goblins_goblin_cobble2.png"},
|
||||
},
|
||||
runaway_from = "player",
|
||||
|
||||
do_custom = function(self)
|
||||
if math.random() < .2 then
|
||||
goblins.search_replace(
|
||||
self,
|
||||
50, --search_rate
|
||||
20, --search_rate_above
|
||||
20, --search_rate_below
|
||||
1, --search_offset
|
||||
2, --search_offset_above
|
||||
1, --search_offset_below
|
||||
20, --replace_rate
|
||||
"default:mossycobble", --replace_what
|
||||
"goblins:moss", --replace_with
|
||||
nil, --replace_rate_secondary
|
||||
nil, --replace_with_secondary
|
||||
nil, --decorate
|
||||
{3}, -- primary and secondary tool index
|
||||
nil --debug messages
|
||||
|
||||
)
|
||||
else
|
||||
goblins.search_replace(
|
||||
self,
|
||||
50, --search_rate
|
||||
20, --search_rate_above
|
||||
20, --search_rate_below
|
||||
1, --search_offset
|
||||
2, --search_offset_above
|
||||
1, --search_offset_below
|
||||
20, --replace_rate
|
||||
{ "group:stone",
|
||||
"group:torch"}, --replace_what
|
||||
"default:mossycobble", --replace_with
|
||||
90, --replace_rate_secondary
|
||||
"goblins:mossycobble_trap", --replace_with_secondary
|
||||
nil, --decorate
|
||||
{1,2}, -- primary and secondary tool index
|
||||
nil --debug messages
|
||||
|
||||
|
||||
|
||||
)
|
||||
end
|
||||
end,
|
||||
additional_properties = {
|
||||
goblin_tools = {
|
||||
"default:mossycobble",
|
||||
"default:axe_stone",
|
||||
"goblins:moss",
|
||||
"default:sword_stone"
|
||||
}
|
||||
},
|
||||
after_activate = function (self)
|
||||
goblins.tool_attach(self,self.goblin_tools)
|
||||
end,
|
||||
spawning = goblins.spawning.cobble
|
||||
--]]
|
||||
--[[
|
||||
goblins.gob_types.foo = {
|
||||
description = S("foo Goblin"),
|
||||
lore = S("foo bar baz"),
|
||||
--you can leave as much as you want undefined as it will be added by the default template in goblins.lua
|
||||
}
|
||||
--]]
|
||||
|
||||
--[[
|
||||
goblins.gobdog_types.zoo = {
|
||||
description = S("zoo Gobdog"),
|
||||
lore = S("zoo bar foo"),
|
||||
--you can leave as much as you want undefined as it will be added by the default template in animals.lua
|
||||
}
|
||||
--]]
|
|
@ -0,0 +1,179 @@
|
|||
|
||||
-- alter this file to adjust goblin/gobdog spawning
|
||||
-- it may be overwritten on update so be sure to back up your changes
|
||||
-- or use a custom file (explained at the bottom)
|
||||
|
||||
goblins.spawning = {
|
||||
digger = {
|
||||
nodes = {"group:stone"},
|
||||
neighbors = "air",
|
||||
min_light = 0,
|
||||
max_light = 10,
|
||||
interval = 30,
|
||||
chance = 1000,
|
||||
active_object_count = 2,
|
||||
min_height = -31000,
|
||||
max_height = -15,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
cobble = {
|
||||
nodes = {"group:stone"},
|
||||
neighbors = "air",
|
||||
min_light = 0,
|
||||
max_light = 10,
|
||||
interval = 30,
|
||||
chance = 1000,
|
||||
active_object_count = 2,
|
||||
min_height = -31000,
|
||||
max_height = -15,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
snuffer = {
|
||||
nodes = {"default:mossycobble"},
|
||||
neighbors = "air",
|
||||
min_light = 0,
|
||||
max_light = 10,
|
||||
interval = 30,
|
||||
chance = 1000,
|
||||
active_object_count = 2,
|
||||
min_height = -31000,
|
||||
max_height = -15,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
fungiler = {
|
||||
nodes = {"default:mossycobble"},
|
||||
neighbors = "air",
|
||||
min_light = 0,
|
||||
max_light = 10,
|
||||
interval = 30,
|
||||
chance = 1500,
|
||||
active_object_count = 1,
|
||||
min_height = -31000,
|
||||
max_height = -15,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
coal = {
|
||||
nodes = {"default:stone_with_coal", "default:mossycobble"},
|
||||
neighbors = "air",
|
||||
min_light = 0,
|
||||
max_light = 10,
|
||||
interval = 20,
|
||||
chance = 500,
|
||||
active_object_count = 3,
|
||||
min_height = -31000,
|
||||
max_height = -25,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
copper = {
|
||||
nodes = {"default:stone_with_copper", "default:mossycobble", "default:blueberries"},
|
||||
neighbors = "air",
|
||||
min_light = 0,
|
||||
max_light = 10,
|
||||
interval = 30,
|
||||
chance = 500,
|
||||
active_object_count = 2,
|
||||
min_height = -31000,
|
||||
max_height = -35,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
iron = {
|
||||
nodes = {"default:stone_with_iron", "default:mossycobble"},
|
||||
neighbors = "air",
|
||||
min_light = 0,
|
||||
max_light = 10,
|
||||
interval = 20,
|
||||
chance = 500,
|
||||
active_object_count = 3,
|
||||
min_height = -31000,
|
||||
max_height = -35,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
gold = {
|
||||
nodes = {"default:stone_with_gold", "default:mossycobble"},
|
||||
neighbors = "air",
|
||||
min_light = 0,
|
||||
max_light = 10,
|
||||
interval = 30,
|
||||
chance = 500,
|
||||
active_object_count = 2,
|
||||
min_height = -31000,
|
||||
max_height = -100,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
diamond = {
|
||||
nodes = {"default:stone_with_diamond", "default:mossycobble"},
|
||||
neighbors = "air",
|
||||
min_light = 0,
|
||||
max_light = 10,
|
||||
interval = 60,
|
||||
chance = 1000,
|
||||
active_object_count = 2,
|
||||
min_height = -31000,
|
||||
max_height = -200,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
hoarder = {
|
||||
nodes = {"default:mossycobble","default:chest"},
|
||||
neighbors = "air",
|
||||
min_light = 0,
|
||||
max_light = 10,
|
||||
interval = 90,
|
||||
chance = 2000,
|
||||
active_object_count = 1,
|
||||
min_height = -31000,
|
||||
max_height = -20,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
gobdog = {
|
||||
nodes = {"default:mossycobble", "group:sand"},
|
||||
min_light = 0,
|
||||
max_light = 14,
|
||||
chance = 500,
|
||||
active_object_count = 4,
|
||||
min_height = -31000,
|
||||
max_height = -20,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
},
|
||||
gobdog_aggro = {
|
||||
nodes = {"default:mossycobble", "group:sand"},
|
||||
min_light = 0,
|
||||
max_light = 6,
|
||||
chance = 500,
|
||||
active_object_count = 1,
|
||||
min_height = -31000,
|
||||
max_height = -100,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
}
|
||||
}
|
||||
|
||||
---you can also override by declaring individual types here as follows:
|
||||
|
||||
goblins.spawning.gobdog = {
|
||||
nodes = {"default:mossycobble", "group:sand"},
|
||||
min_light = 0,
|
||||
max_light = 14,
|
||||
chance = 500,
|
||||
active_object_count = 4,
|
||||
min_height = -31000,
|
||||
max_height = -20,
|
||||
day_toggle = nil,
|
||||
on_spawn = nil,
|
||||
}
|
||||
|
||||
-- alternatively you can make a custom file with something like:
|
||||
|
||||
-- dofile(path .. "/goblins_spawning_custom.lua")
|
||||
|
||||
-- and declare your overrides there.
|
|
@ -0,0 +1,169 @@
|
|||
local saved_huds = {}
|
||||
|
||||
local ght = tonumber(minetest.settings:get("goblins_hud_timer")) or 0
|
||||
|
||||
local function clear_hud(params)
|
||||
|
||||
local player = minetest.get_player_by_name(params[1])
|
||||
local meta = player:get_meta()
|
||||
--print ("testing"..dump(params))
|
||||
if os.time() >= (meta:get_int("hud_time_start") + ght) then
|
||||
player:hud_remove(params[2])
|
||||
meta:set_int("hud_cleared",1)
|
||||
--print ("removing"..dump(params))
|
||||
end
|
||||
end
|
||||
function goblins.update_hud(player)
|
||||
if ght > 0 then
|
||||
--for _,player in ipairs(minetest.get_connected_players()) do
|
||||
local player_name = player:get_player_name()
|
||||
--print(player_name)
|
||||
local meta = player:get_meta()
|
||||
local goblin_current = meta:get_string("goblin_current")
|
||||
local territory_current = meta:get_string("territory_current")
|
||||
local known_territories = minetest.deserialize(meta:get_string("territory_list"))
|
||||
local territory = "unknown"
|
||||
if known_territories then
|
||||
for k,v in pairs(known_territories) do
|
||||
if territory_current == v then
|
||||
territory = v
|
||||
end
|
||||
end
|
||||
end
|
||||
local text_goblin_current = goblin_current
|
||||
local text_territory_current = "of " ..territory
|
||||
local territory_score_table = minetest.deserialize(meta:get_string(territory_current))
|
||||
local text_territory_scores = {}
|
||||
if not territory_score_table then return end
|
||||
for k,v in pairs(territory_score_table) do
|
||||
text_territory_scores[k] = k..": "..v
|
||||
end
|
||||
|
||||
local ids = saved_huds[player_name]
|
||||
|
||||
if not ids then
|
||||
ids = {}
|
||||
ids.territory_scores = {}
|
||||
saved_huds[player_name] = ids
|
||||
-- create HUD elements and set ids into `ids`
|
||||
--[[
|
||||
player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0.5},
|
||||
offset = {x = -120, y = -25},
|
||||
text = "Goblin HUD",
|
||||
alignment = -0,
|
||||
scale = { x = 100, y = 30},
|
||||
number = 0xFFFFFF,
|
||||
})
|
||||
--]]
|
||||
ids.goblin_current = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0.5},
|
||||
offset = {x = -120, y = -25},
|
||||
text = text_goblin_current,
|
||||
alignment = -1,
|
||||
scale = { x = 50, y = 10},
|
||||
number = 0xFFFFFF,
|
||||
})
|
||||
local params = {player_name,ids.goblin_current}
|
||||
minetest.after((ght+5),clear_hud, params)
|
||||
ids.territory_current = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0.5},
|
||||
offset = {x = -120, y = 0},
|
||||
text = text_territory_current,
|
||||
alignment = -1,
|
||||
scale = { x = 50, y = 10},
|
||||
number = 0xFFFFFF,
|
||||
})
|
||||
local params = {player_name,ids.territory_current}
|
||||
minetest.after((ght+5),clear_hud, params)
|
||||
local tst_yo = 0
|
||||
for k,v in pairs(territory_score_table) do
|
||||
tst_yo = tst_yo + 20
|
||||
ids.territory_scores[k] = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0.5},
|
||||
offset = {x = -120, y = tst_yo},
|
||||
text = text_territory_scores[k],
|
||||
alignment = -1,
|
||||
scale = { x = 50, y = 10},
|
||||
number = 0xFFFFFF,
|
||||
})
|
||||
local params = {player_name,ids.territory_scores[k]}
|
||||
minetest.after(ght+5,clear_hud, params)
|
||||
end
|
||||
|
||||
--minetest.after(ght,clear_hud, params)
|
||||
else
|
||||
if meta:get_int("hud_cleared") == 1 then
|
||||
--hud_params_title()
|
||||
ids.goblin_current = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0.5},
|
||||
offset = {x = -120, y = -25},
|
||||
text = text_goblin_current,
|
||||
alignment = -1,
|
||||
scale = { x = 50, y = 10},
|
||||
number = 0xFFFFFF,
|
||||
})
|
||||
local params = {player_name,ids.goblin_current}
|
||||
minetest.after(ght,clear_hud, params)
|
||||
ids.territory_current = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0.5},
|
||||
offset = {x = -120, y = 0},
|
||||
text = text_territory_current,
|
||||
alignment = -1,
|
||||
scale = { x = 50, y = 10},
|
||||
number = 0xFFFFFF,
|
||||
})
|
||||
local params = {player_name,ids.territory_current}
|
||||
minetest.after(ght,clear_hud, params)
|
||||
local tst_yo = 0
|
||||
for k,v in pairs(territory_score_table) do
|
||||
tst_yo = tst_yo + 20
|
||||
ids.territory_scores[k] = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0.5},
|
||||
offset = {x = -120, y = tst_yo},
|
||||
text = text_territory_scores[k],
|
||||
alignment = -1,
|
||||
scale = { x = 50, y = 10},
|
||||
number = 0xFFFFFF,
|
||||
})
|
||||
local params = {player_name,ids.territory_scores[k]}
|
||||
minetest.after(ght,clear_hud, params)
|
||||
end
|
||||
else
|
||||
local params = {player_name,ids.goblin_current}
|
||||
player:hud_change(ids["goblin_current"], "text", text_goblin_current)
|
||||
minetest.after(ght,clear_hud, params)
|
||||
local params = {player_name,ids.territory_current}
|
||||
player:hud_change(ids["territory_current"], "text", text_territory_current)
|
||||
minetest.after(ght,clear_hud, params)
|
||||
for k,v in pairs(territory_score_table) do
|
||||
local params = {player_name,ids.territory_scores[k]}
|
||||
minetest.after(ght,clear_hud, params)
|
||||
player:hud_change(ids.territory_scores[k],"text", text_territory_scores[k])
|
||||
end
|
||||
--player:hud_change(ids["bar_foreground"],
|
||||
--"scale", { x = percent, y = 1 })
|
||||
end
|
||||
end
|
||||
meta:set_int("hud_cleared",0)
|
||||
meta:set_int("hud_time_start",os.time())
|
||||
--minetest.after(ght, print,"ONE" )
|
||||
-- minetest.after(ght-1, print,"TWO" )
|
||||
-- minetest.after(ght-2, print,"THREE")
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
minetest.register_on_joinplayer(goblins.update_hud)
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
saved_huds[player:get_player_name()] = nil
|
||||
end)
|
|
@ -0,0 +1,18 @@
|
|||
-- optional hunger api mod: https://gitlab.com/4w/hunger_ng
|
||||
|
||||
if minetest.get_modpath("hunger_ng") then
|
||||
print("Hunger NG mod detected, looking for API..")
|
||||
if hunger_ng and hunger_ng.add_hunger_data then
|
||||
print("Hunger NG mod API loaded")
|
||||
local add = hunger_ng.add_hunger_data
|
||||
add("goblins:mushroom_goblin", { satiates = 1.5 })
|
||||
add("goblins:mushroom_goblin2", { satiates = 2.0 })
|
||||
add("goblins:mushroom_goblin3", { satiates = 2.2 })
|
||||
add("goblins:mushroom_goblin4", { satiates = 2.5 })
|
||||
else
|
||||
print(dump( minetest.get_modpath("hunger_ng") ))
|
||||
print("Hunger NG mod API not found")
|
||||
print("Please check latest version of Hunger NG at")
|
||||
print("https://gitlab.com/4w/hunger_ng")
|
||||
end
|
||||
end
|
|
@ -1,11 +1,113 @@
|
|||
local path = minetest.get_modpath("mobs_goblins")
|
||||
local path = minetest.get_modpath("goblins")
|
||||
goblins_db = minetest.get_mod_storage()
|
||||
goblins_db:set_string("goblins mod start time", os.date() )
|
||||
--set namespace for goblins functions
|
||||
goblins = {}
|
||||
|
||||
-- Mob Api
|
||||
goblins.version = "20210421"
|
||||
|
||||
dofile(path.."/api.lua")
|
||||
dofile(path.."/goblins.lua") -- TenPlus1 and FreeLikeGNU
|
||||
dofile(path.."/goblin_traps.lua")
|
||||
-- Strips any kind of escape codes (translation, colors) from a string
|
||||
-- https://github.com/minetest/minetest/blob/53dd7819277c53954d1298dfffa5287c306db8d0/src/util/string.cpp#L777
|
||||
function goblins.strip_escapes(input)
|
||||
local s = function(idx) return input:sub(idx, idx) end
|
||||
local out = ""
|
||||
local i = 1
|
||||
while i <= #input do
|
||||
if s(i) == "\027" then -- escape sequence
|
||||
i = i + 1
|
||||
if s(i) == "(" then -- enclosed
|
||||
i = i + 1
|
||||
while i <= #input and s(i) ~= ")" do
|
||||
if s(i) == "\\" then
|
||||
i = i + 2
|
||||
else
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
out = out .. s(i)
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
--print(("%q -> %q"):format(input, out))
|
||||
return out
|
||||
end
|
||||
|
||||
local function print_s(input)
|
||||
print(goblins.strip_escapes(input))
|
||||
end
|
||||
|
||||
local S = minetest.get_translator("goblins")
|
||||
|
||||
local goblins_version = goblins.version
|
||||
-- create the table if it does not exist!
|
||||
local goblins_db_fields = goblins_db:to_table()["fields"]
|
||||
local function goblins_db_write(key, table)
|
||||
local data = minetest.serialize(table)
|
||||
goblins_db:set_string(key, data)
|
||||
return key, data
|
||||
end
|
||||
if not goblins_db_fields["territories"] then
|
||||
print("-------------\nWe must Initialize!\n-------------")
|
||||
goblins_db_write("territories", {test = {version = goblins_version, encode = minetest.encode_base64(os.date()), created = os.date() }})
|
||||
end
|
||||
if not goblins_db_fields["relations"] then
|
||||
print("-------------\nWe must Initialize!\n-------------")
|
||||
goblins_db_write("relations", {test = {version = goblins_version, encode = minetest.encode_base64(os.date()), created = os.date() }})
|
||||
end
|
||||
--compatability with minimal game
|
||||
if not default.LIGHT_MAX then
|
||||
default.LIGHT_MAX = 14
|
||||
LIGHT_MAX = default.LIGHT_MAX
|
||||
end
|
||||
|
||||
minetest.log("action", "[MOD] goblins " ..goblins.version.. " is lowdings....")
|
||||
print_s(S("Please report issues at https://github.com/FreeLikeGNU/goblins/issues "))
|
||||
|
||||
if mobs.version then
|
||||
if tonumber(mobs.version) >= tonumber(20200516) then
|
||||
print_s(S("Mobs Redo 20200516 or greater found!"))
|
||||
else
|
||||
print_s(S("You should find a more recent version of Mobs Redo!"))
|
||||
print_s(S("https://notabug.org/TenPlus1/mobs_redo"))
|
||||
end
|
||||
else
|
||||
print_s(S("This mod requires Mobs Redo version 2020516 or greater!"))
|
||||
print_s(S("https://notabug.org/TenPlus1/mobs_redo"))
|
||||
end
|
||||
|
||||
dofile(path .. "/utilities.lua")
|
||||
dofile(path .. "/traps.lua")
|
||||
dofile(path .. "/nodes.lua")
|
||||
--if minetest.settings:get("log_mods") then
|
||||
minetest.log("action", "GOBLINS is lowdids!")
|
||||
--end
|
||||
dofile(path .. "/items.lua")
|
||||
dofile(path .. "/soundsets.lua")
|
||||
dofile(path .. "/behaviors.lua")
|
||||
dofile(path .. "/goblins_spawning.lua")
|
||||
dofile(path .. "/animals.lua")
|
||||
dofile(path .. "/goblins.lua")
|
||||
dofile(path .. "/hunger.lua")
|
||||
dofile(path .. "/goblins_custom.lua") --allow for additional/replacement goblins created by user
|
||||
dofile(path .. "/hud.lua")
|
||||
-------------
|
||||
--ASSEMBLE THE GOBLIN HORDES!!!!
|
||||
-------------
|
||||
|
||||
local gob_types = goblins.gob_types
|
||||
local gobdog_types = goblins.gobdog_types
|
||||
local goblin_template = goblins.goblin_template
|
||||
local gobdog_template = goblins.gobdog_template
|
||||
local gob_name_parts = goblins.gob_name_parts
|
||||
local gob_words = goblins.words_desc
|
||||
|
||||
goblins.generate(gob_types,goblin_template)
|
||||
goblins.generate(gobdog_types,gobdog_template)
|
||||
|
||||
local function ggn(gob_name_parts,rules)
|
||||
return goblins.generate_name(gob_name_parts,rules)
|
||||
end
|
||||
|
||||
print_s(S("This diversion is dedicated to the memory of @1 the @2, @3 the @4, and @5 the @6... May their hordes be mine!",
|
||||
ggn(gob_name_parts),ggn(gob_words, {"tool_adj"}),ggn(gob_name_parts),ggn(gob_words, {"tool_adj"}),ggn(gob_name_parts),ggn(gob_words, {"tool_adj"})))
|
||||
print_s(S(" --@1 of the @2 clan.",ggn(gob_name_parts),ggn(gob_name_parts,{"list_a","list_opt","-","list_b"})))
|
||||
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
--more things to craft soon...
|
||||
local craft_ingreds = {
|
||||
mossycobble = "default:mossycobble",
|
||||
}
|
||||
|
||||
for name, mat in pairs(craft_ingreds) do
|
||||
minetest.register_craft({
|
||||
output = "goblins:pick_".. name,
|
||||
recipe = {
|
||||
{mat, mat, mat},
|
||||
{"", "group:stick", ""},
|
||||
{"", "group:stick", ""}
|
||||
}
|
||||
})
|
||||
end
|
||||
minetest.register_tool("goblins:pick_mossycobble", {
|
||||
description = "Mossycobble Pickaxe",
|
||||
inventory_image = "default_tool_stonepick.png",
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 1.2,
|
||||
max_drop_level=0,
|
||||
groupcaps={
|
||||
cracky = {times={[2]=1.8, [3]=0.90}, uses=25, maxlevel=1},
|
||||
},
|
||||
damage_groups = {fleshy=3},
|
||||
},
|
||||
sound = {breaks = "default_tool_breaks"},
|
||||
groups = {pickaxe = 1}
|
||||
})
|
||||
|
||||
local goblin_tool = {}
|
||||
goblin_tool = {
|
||||
initial_properties = {
|
||||
--physical = true,
|
||||
pointable = false,
|
||||
collisionbox = {0,0,0,0,0,0},
|
||||
visual = "wielditem",
|
||||
visual_size = {x = 0.15, y = 0.15},
|
||||
wield_item = "default:stick",
|
||||
},
|
||||
message = "Default message",
|
||||
on_step = function(self)
|
||||
if not self.owner or not self.owner:get_luaentity() then
|
||||
self.object:remove()
|
||||
else
|
||||
if self.owner:get_luaentity().current_tool ~= self.tool_name then
|
||||
--print("removing old tool: "..self.tool_name.." for "..self.owner:get_luaentity().current_tool)
|
||||
self.object:set_detach()
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
local function tool_check(tool)
|
||||
if not minetest.registered_entities[tool] and
|
||||
not minetest.registered_tools[tool] and
|
||||
not minetest.registered_items[tool] and
|
||||
not minetest.registered_craftitems[tool] and
|
||||
not minetest.registered_nodes[tool] then
|
||||
return
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function tool_gen_engine(tool)
|
||||
local tool_table = string.split(tool,":")
|
||||
local tool_string = tool_table[1].."_"..tool_table[2]
|
||||
--print("tool string 1: "..tool_string)
|
||||
local gen_tool = table.copy(goblin_tool)
|
||||
gen_tool.initial_properties.wield_item = tool
|
||||
--print("goblin tool "..dump(goblin_tool))
|
||||
--tool_string = "default_stick"
|
||||
local ent_name = "goblins:goblin_tool_"..tool_string
|
||||
--print("trying "..ent_name )
|
||||
if not minetest.registered_entities[ent_name] then
|
||||
minetest.register_entity(ent_name,gen_tool)
|
||||
-- print("registered "..ent_name )
|
||||
else
|
||||
-- print("*** goblin tool: "..ent_name.." already registered! ***")
|
||||
end
|
||||
--return tool_string
|
||||
end
|
||||
|
||||
function goblins.tool_gen(tool)
|
||||
-- if not tool_check(tool) then
|
||||
-- tool = "default:stick"
|
||||
-- end
|
||||
if type(tool) == "table" then
|
||||
for k,v in pairs(tool) do
|
||||
tool_gen_engine(v)
|
||||
end
|
||||
else
|
||||
tool_gen_engine(tool)
|
||||
end
|
||||
end
|
||||
|
||||
local function tool_attach_engine(self,tool)
|
||||
local tool_table = string.split(tool,":")
|
||||
local tool_string = tool_table[1].."_"..tool_table[2]
|
||||
--print("tool string 2: "..tool_string)
|
||||
--print("testing attach: "..dump(tool_gen(tool)))
|
||||
local tool_name = "goblins:goblin_tool_"..tool_string
|
||||
--..tool_gen(tool)
|
||||
--print("tool name:"..tool_name)
|
||||
local item = minetest.add_entity(self.object:get_pos(), tool_name)
|
||||
item:set_attach(self.object, "Arm_Right", {x=0.15, y=2.0, z=1.75}, {x=-90, y=180, z=90})
|
||||
--print(dump(self.goblin_tools))
|
||||
item:get_luaentity().owner = self.object
|
||||
self.current_tool = tool
|
||||
item:get_luaentity().tool_name = tool
|
||||
end
|
||||
|
||||
local function wrandom(wtable)
|
||||
local chance = #wtable
|
||||
for _,__ in pairs(wtable) do
|
||||
local test = chance * math.random(chance)
|
||||
if chance == math.random(test) then
|
||||
return wtable[chance]
|
||||
else chance = chance - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function goblins.tool_attach(self,tool)
|
||||
--print(dump(tool))
|
||||
-- if not tool_check(tool) then
|
||||
-- tool = "default:stick"
|
||||
-- end
|
||||
if type(tool) == "table" then
|
||||
local rnd_tool = wrandom(tool)
|
||||
-- print("attaching "..rnd_tool)
|
||||
-- local rnd_tool = tool[math.random(1,#tool)]
|
||||
tool_attach_engine(self,rnd_tool)
|
||||
--print("attaching "..rnd_tool)
|
||||
else
|
||||
tool_attach_engine(self,tool)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
name = goblins
|
||||
descriptions = add goblins that dig tunnels, set traps and create lairs.
|
||||
depends = default, mobs
|
||||
optional_depends = ambience, hunger_ng
|
|
@ -1,9 +1,327 @@
|
|||
|
||||
minetest.register_node(":default:mossycobble", {
|
||||
description = "Mossy Cobblestone",
|
||||
tiles = {"default_mossycobble.png"},
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 3, stone = 1},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
sounds = default.node_sound_stone_defaults({
|
||||
footstep = {name = "goblins_mossycobble_footstep", gain = 0.4},
|
||||
}),
|
||||
paramtype = "light",
|
||||
light_source = 4,
|
||||
light_source = 0,
|
||||
})
|
||||
|
||||
minetest.register_node("goblins:moss", {
|
||||
description = "Moss",
|
||||
inventory_image = "default_moss.png",
|
||||
tiles = {
|
||||
"default_moss.png^[colorize:#222222:150",
|
||||
},
|
||||
paramtype = "light",
|
||||
|
||||
drawtype = "normal",
|
||||
walkable = true,
|
||||
buildable_to = true,
|
||||
is_ground_content = false,
|
||||
groups = {crumbly = 3,slippery = 2, falling_node = 1, },
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name = "goblins_mossycobble_footstep", gain = 0.4},
|
||||
}),
|
||||
|
||||
light_source = 4,
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
--print("node meta:"..dump(meta))
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_node("goblins:mossx", {
|
||||
description = "Moss",
|
||||
inventory_image = "default_moss.png",
|
||||
tiles = {
|
||||
"default_moss.png^[colorize:#222222:150",
|
||||
"default_moss.png^[colorize:#222222:150",
|
||||
"default_moss.png^[colorize:#222222:150",
|
||||
"default_moss.png^[colorize:#222222:150",
|
||||
"default_moss.png^[colorize:#222222:150",
|
||||
"default_moss.png^[colorize:#222222:150",
|
||||
},
|
||||
paramtype2="wallmounted",
|
||||
paramtype = "light",
|
||||
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "wallmounted",
|
||||
wall_bottom = {-0.5, -0.5, -0.5, 0.5, -0.45, 0.5}, -- bottom
|
||||
wall_top = {-0.5, 0.45, -0.5, 0.5, 0.5, 0.5}, -- top
|
||||
wall_side = {-0.45, -0.5, -0.5, -0.5, 0.5, 0.5} -- side
|
||||
|
||||
},
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
is_ground_content = false,
|
||||
groups = {crumbly = 3,slippery = 2, falling_node = 1, attached_node = 1},
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name = "goblins_mossycobble_footstep", gain = 0.4},
|
||||
}),
|
||||
|
||||
light_source = 2,
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
--print("node meta:"..dump(meta))
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_node("goblins:mushroom_goblin", {
|
||||
description = "gobble mushroom",
|
||||
tiles = {"goblins_mushroom_brown.png^(default_grass_1.png^[opacity:150)"},
|
||||
inventory_image = "goblins_mushroom_brown.png",
|
||||
wield_image = "goblins_mushroom_brown.png",
|
||||
drawtype = "firelike",
|
||||
paramtype = "light",
|
||||
paramtype2="wallmounted",
|
||||
light_source = 2,
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
climbable = true,
|
||||
floodable = true,
|
||||
groups = {float = 1, mushroom = 1, food_mushroom = 1, snappy = 3, attached_node = 1, flammable = 1},
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
on_use = minetest.item_eat(2),
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-3 / 16, -0.5, -3 / 16, 3 / 16, -2 / 16, 3 / 16},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("goblins:mushroom_goblin2", {
|
||||
description = "gobble mushroom",
|
||||
tiles = {"goblins_mushroom_brown2.png^(default_grass_1.png^[opacity:150)"},
|
||||
inventory_image = "goblins_mushroom_brown2.png",
|
||||
wield_image = "goblins_mushroom_brown.png",
|
||||
drawtype = "firelike",
|
||||
paramtype = "light",
|
||||
paramtype2="wallmounted",
|
||||
light_source = 2,
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
climbable = true,
|
||||
floodable = true,
|
||||
groups = {float = 1, mushroom = 1, food_mushroom = 2, snappy = 3, attached_node = 1, flammable = 1},
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
on_use = minetest.item_eat(2),
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-3 / 16, -0.5, -3 / 16, 3 / 16, -2 / 16, 3 / 16},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("goblins:mushroom_goblin3", {
|
||||
description = "gobble mushroom",
|
||||
tiles = {"goblins_mushroom_brown3.png^(default_grass_1.png^[opacity:150)"},
|
||||
inventory_image = "goblins_mushroom_brown3.png",
|
||||
wield_image = "goblins_mushroom_brown.png",
|
||||
drawtype = "firelike",
|
||||
paramtype = "light",
|
||||
paramtype2="wallmounted",
|
||||
light_source = 2,
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
climbable = true,
|
||||
floodable = true,
|
||||
groups = {float = 1, mushroom = 1, food_mushroom = 3, snappy = 3, attached_node = 1, flammable = 1},
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
on_use = minetest.item_eat(2),
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-3 / 16, -0.5, -3 / 16, 3 / 16, -2 / 16, 3 / 16},
|
||||
}
|
||||
})
|
||||
minetest.register_node("goblins:mushroom_goblin4", {
|
||||
description = "gobble mushroom",
|
||||
tiles = {"goblins_mushroom_brown4.png^(default_grass_1.png^[opacity:150)"},
|
||||
inventory_image = "goblins_mushroom_brown4.png",
|
||||
wield_image = "goblins_mushroom_brown.png",
|
||||
drawtype = "firelike",
|
||||
paramtype = "light",
|
||||
paramtype2="wallmounted",
|
||||
light_source = 2,
|
||||
sunlight_propagates = true,
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
climbable = true,
|
||||
floodable = true,
|
||||
groups = {float = 1, mushroom = 1, food_mushroom = 4, snappy = 3, attached_node = 1, flammable = 1},
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
on_use = minetest.item_eat(2),
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-3 / 16, -0.5, -3 / 16, 3 / 16, -2 / 16, 3 / 16},
|
||||
}
|
||||
})
|
||||
|
||||
function goblins.moss_spread(pos, node)
|
||||
if minetest.get_node_light(pos, 0.5) > 6 then
|
||||
if minetest.get_node_light(pos, nil) == 15 then
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
return
|
||||
end
|
||||
--print("moss spread abm"..minetest.pos_to_string(pos))
|
||||
if math.random() < 0.1 then
|
||||
|
||||
minetest.set_node(pos,{name = "goblins:mushroom_goblin"})
|
||||
else
|
||||
local positions = minetest.find_nodes_in_area_under_air(
|
||||
{x = pos.x - 1, y = pos.y - 2, z = pos.z - 1},
|
||||
{x = pos.x + 1, y = pos.y + 1, z = pos.z + 1},
|
||||
{"default:mossycobble","group:choppy"})
|
||||
|
||||
if #positions == 0 or pos.y > -10 then
|
||||
return
|
||||
end
|
||||
local pos2 = positions[math.random(#positions)]
|
||||
pos2.y = pos2.y + 1
|
||||
if minetest.get_node_light(pos2, 0.5) <= 5 then
|
||||
minetest.set_node(pos2, {name = node.name})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function goblins.mushroom_spread(pos, node)
|
||||
if minetest.get_node_light(pos, 0.5) > 6 then
|
||||
if minetest.get_node_light(pos, nil) == 15 then
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
return
|
||||
end
|
||||
--print("mushroom spread abm"..minetest.pos_to_string(pos))
|
||||
local positions = minetest.find_nodes_in_area_under_air(
|
||||
{x = pos.x - 1, y = pos.y - 2, z = pos.z - 1},
|
||||
{x = pos.x + 1, y = pos.y + 1, z = pos.z + 1},
|
||||
{"default:mossycobble"})
|
||||
if #positions == 0 or pos.y > -10 then
|
||||
return
|
||||
end
|
||||
local pos2 = positions[math.random(#positions)]
|
||||
pos2.y = pos2.y + 1
|
||||
if minetest.get_node_light(pos2, 0.5) <= 5 then
|
||||
minetest.set_node(pos2, {name = node.name})
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Moss spread",
|
||||
nodenames = {"goblins:moss"},
|
||||
interval = 50,
|
||||
chance = 50,
|
||||
action = function(...)
|
||||
goblins.moss_spread(...)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Mushroom spread",
|
||||
nodenames = {"goblins:mushroom_goblin","goblins:mushroom_goblin2","goblins:mushroom_goblin3","goblins:mushroom_goblin4"},
|
||||
interval = 100,
|
||||
chance = 100,
|
||||
action = function(...)
|
||||
goblins.mushroom_spread(...)
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_node("goblins:goblins_goblin_bone", {
|
||||
description = "gnawed bone",
|
||||
tiles = {"goblins_goblin_bone.png"},
|
||||
inventory_image = "goblins_goblin_bone.png",
|
||||
visual_scale = 0.7,
|
||||
drawtype = "plantlike",
|
||||
wield_image = "goblins_goblin_bone.png",
|
||||
paramtype = "light",
|
||||
walkable = false,
|
||||
is_ground_content = true,
|
||||
sunlight_propagates = true,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.2, -0.5, -0.2, 0.2, 0, 0.2}
|
||||
},
|
||||
groups = {bone = 1, meat = 1, snappy = 2, fleshy =1, dig_immediate = 3},
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
if placer:is_player() then
|
||||
minetest.set_node(pos, {name = "goblins:goblins_goblin_bone", param2 = 1})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("goblins:goblins_goblin_bone_meaty", {
|
||||
description = "meaty bone",
|
||||
tiles = {"goblins_goblin_bone_meaty.png"},
|
||||
inventory_image = "goblins_goblin_bone_meaty.png",
|
||||
visual_scale = 0.7,
|
||||
drawtype = "plantlike",
|
||||
wield_image = "goblins_goblin_bone_meaty.png",
|
||||
paramtype = "light",
|
||||
walkable = false,
|
||||
is_ground_content = true,
|
||||
sunlight_propagates = true,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.2, -0.5, -0.2, 0.2, 0, 0.2}
|
||||
},
|
||||
groups = {meat = 1, snappy = 2, fleshy =3, dig_immediate = 3},
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
if placer:is_player() then
|
||||
minetest.set_node(pos, {name = "goblins:goblins_goblin_bone_meaty", param2 = 1})
|
||||
end
|
||||
end,
|
||||
})
|
||||
---from minetest default mod: nodes
|
||||
minetest.register_node("goblins:dirt_with_bone", {
|
||||
description = "Dirt with something buried",
|
||||
tiles = {"default_dirt.png^default_stones.png",
|
||||
{name = "default_dirt.png^goblins_goblin_bone.png",
|
||||
tileable_vertical = false}},
|
||||
groups = {crumbly = 3, soil = 1,
|
||||
--not_in_creative_inventory = 1
|
||||
},
|
||||
drop = {
|
||||
max_items = 1, -- Only one set of item will be dropped.
|
||||
items = {
|
||||
{
|
||||
items = {"default:flint 1", "goblins:goblins_goblin_bone 2","default:stick"},
|
||||
rarity = 2, -- has 1 chance over 2 to be picked
|
||||
},
|
||||
{items = {"goblins:goblins_goblin_bone"}}
|
||||
}
|
||||
},
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name = "default_grass_footstep", gain = 0.25},
|
||||
}),
|
||||
})
|
||||
|
||||
minetest.register_node("goblins:dirt_with_stuff", {
|
||||
description = "Dirt with something shiny buried",
|
||||
tiles = {"default_dirt.png^default_mineral_tin.png^default_stones.png",
|
||||
{name = "default_dirt.png^default_mineral_tin.png^goblins_goblin_bone.png",
|
||||
tileable_vertical = false}},
|
||||
groups = {crumbly = 3, soil = 1,
|
||||
--not_in_creative_inventory = 1
|
||||
},
|
||||
drop = {
|
||||
max_items = 2, -- Only one set of item will be dropped.
|
||||
items = {
|
||||
{
|
||||
items = {"default:pick_steel", "default:meselamp"},
|
||||
rarity = 16, -- has 1 chance over 16 to be picked
|
||||
},
|
||||
{items = {"goblins:goblins_goblin_bone","default:shovel_steel"}}
|
||||
}
|
||||
},
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name = "default_grass_footstep", gain = 0.25},
|
||||
}),
|
||||
})
|
|
@ -0,0 +1,35 @@
|
|||
Goblins Relations and Territory storage
|
||||
|
||||
Relations are tables that are stored in the mobs self.relations as tables and in the mod data storage as serialized strings
|
||||
these tables are currently meant to provide a way to show the relations of:
|
||||
|
||||
* Mobs to a territory (defined by both the mob and territory secret names generated on spawn)
|
||||
* Players to a mob (defined by playername and a table of keys/value pairs describing relationship parameters)
|
||||
|
||||
In this way way can jump into the table using only the keys of the mob, player and relavent parameters to avoid searches and iterations
|
||||
|
||||
|
||||
sample relation table from self.relations with "Unkadz" as "self.secret_name" and "Khad-glat" as "self.secret_territory" :
|
||||
Unkadz = {
|
||||
ix = 1588945576,
|
||||
Unkadz = "Khad-glat",
|
||||
freelikegnu = {
|
||||
trade = 52
|
||||
aggro = 10
|
||||
}
|
||||
}
|
||||
|
||||
in functions:
|
||||
Relations should always be checked by the goblins.relations(self, target_name, target_table) function.
|
||||
With only the "self" variable defined, this function will check if a relations root table has been established
|
||||
and create one if not yet existing in both the mobs self.relations table and in the mod storage.
|
||||
This function will then return all existing relations as recorded. Use this as a basis to further alter the relations if needed.
|
||||
|
||||
With both self and target_name declared (with target_name being that of a player or even the self.secret_name of a mob)
|
||||
The function will do as above and initialize a relation between self and the target_name entity if none already exists
|
||||
This function will then return only the existing relations between self and target_name as recorded. Use this as a basis to further alter the relations between two entitities if needed to only edit the keys from the target_name to the self.
|
||||
|
||||
Any actual manipulations of existing relationships should be handled by goblins.relations(self, target_name, target_table) with all arguements declared. This will overwrite any existing value of the target_table that may have been stored in the self.relations[target_name][target_table] , so be sure that you have gathered and altered the table before invoking this way!
|
||||
|
||||
spawning a mob will generate its name and territory if these are not already present
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# goblins_hud_timer: time in seconds the goblins HUD will be visible following interactions (0 disables HUD)
|
||||
goblins_hud_timer (goblins HUD timer for interactions) int 0
|
||||
# goblins_aggro_on_wield: will goblins attack when a weapon is wielded?
|
||||
goblins_aggro_on_wield (goblins attack when a weapon is wielded) bool true
|
||||
# goblins_defend_groups: will goblins and gobdogs defend other mobs?
|
||||
goblins_defend_groups (goblins and gobdogs defend other mobs) bool true
|
||||
|
||||
# trade shrewdness increases trade difficulty
|
||||
goblins_trade_shrewdness (trade shrewdness increases trade difficulty) int 20
|
||||
|
||||
# use strict protection if node protection is activated (otherwise mobs can replace nodes they are close to)
|
||||
goblins_node_protect_strict (use strict protection if node protection is activated) bool true
|
||||
|
||||
# utilities debug output announce_spawning
|
||||
debug_goblins_announce_spawning (utilities debug output announce_spawning) bool false
|
||||
# utilities debug output goblins_relations
|
||||
debug_goblins_relations (utilities debug output goblins_relations) bool false
|
||||
# utilities debug output goblins_secret
|
||||
debug_goblins_secret (utilities debug output goblins_secret) bool false
|
||||
# utilities debug output goblins_territories
|
||||
debug_goblins_territories (utilities debug output goblins_territories) bool false
|
||||
# utilities debug output goblins_territory_relations
|
||||
debug_goblins_territory_relations (utilities debug output goblins_territory_relations) bool false
|
||||
# utilities debug output goblins_trade_relations
|
||||
debug_goblins_trade_relations (utilities debug output goblins_trade_relations) bool false
|
||||
|
||||
# behaviors debug output attack
|
||||
debug_goblins_attack (behaviors debug output attack) bool false
|
||||
# behaviors debug output find
|
||||
debug_goblins_find (behaviors debug output find) bool false
|
||||
# behaviors debug output replace
|
||||
debug_goblins_replace (behaviors debug output replace) bool false
|
||||
# debug output replace2
|
||||
debug_goblins_replace2 (behaviors debug output replace2) bool false
|
||||
# behaviors debug output search
|
||||
debug_goblins_search (behaviors debug output search) bool false
|
||||
# behaviors debug output tunneling
|
||||
debug_goblins_tunneling (behaviors debug output tunneling) bool false
|
||||
# behaviors debug output trade
|
||||
debug_goblins_trade (behaviors debug output trade) bool false
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
-- optional ambience api mod: https://notabug.org/TenPlus1/ambience
|
||||
|
||||
if minetest.get_modpath("ambience") then
|
||||
|
||||
print("Ambience Lite mod detected, looking for API..")
|
||||
if ambience then
|
||||
print("Ambience mod API loaded")
|
||||
if ambience.get_set("cave") then
|
||||
ambience.del_set("cave")
|
||||
end
|
||||
ambience.add_set("underground", {
|
||||
frequency = 1000,
|
||||
sounds = {
|
||||
{name = "goblins_ambient_underground", length = 25}
|
||||
},
|
||||
sound_check = function(def)
|
||||
--[[ local c = (def.totals["default:mossycobble"] or 0)
|
||||
+ (def.totals["default:stone"] or 0)
|
||||
if c > 5 then--]]
|
||||
if def.pos.y < -15 then
|
||||
return "underground"
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
--Does not seem to be working as expected, but maybe someday:
|
||||
ambience.add_set("mossycobble", {
|
||||
frequency = 100,
|
||||
sounds = {
|
||||
{name = "goblins_ambient_drip", length = 11.4}
|
||||
},
|
||||
sound_check = function(def)
|
||||
local c = (def.totals["default:mossycobble"] or 0)
|
||||
|
||||
if c > 10 and def.pos.y < -15 then
|
||||
|
||||
return "mossycobble"
|
||||
end
|
||||
end,
|
||||
})
|
||||
else
|
||||
print(dump( minetest.get_modpath("ambience") ))
|
||||
print("Ambience Lite mod API not found")
|
||||
print("Please check latest version of Ambience Lite at")
|
||||
print("https://notabug.org/TenPlus1/ambience")
|
||||
end
|
||||
end
|
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 169 B |
After Width: | Height: | Size: 690 B |
After Width: | Height: | Size: 728 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 274 B |
After Width: | Height: | Size: 355 B |
After Width: | Height: | Size: 313 B |
After Width: | Height: | Size: 358 B |
|
@ -1,2 +1,5 @@
|
|||
goblins_lightning https://openclipart.org/detail/36343/lightning-08
|
||||
goblins_molten_gold* http://commons.wikimedia.org/wiki/File:Villarrica_lava_fountain.jpg and VanessaE (HDX Textures)
|
||||
|
||||
mushrooms.xcf Copyright Francisco Athens (CC BY-SA 3.0) 2020
|
||||
goblins_mushroom_brown.png, goblins_mushroom_brown2.png goblins_mushroom_brown3.png goblins_mushroom_brown4.png Copyright Francisco Athens (CC BY-SA 3.0) 2020
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
--[[some nasty things goblins can do]]
|
||||
-- Many thanks for AntumDeluge https://github.com/AntumDeluge for replacing the depcrecated methods!
|
||||
--Super thanks to duane-r for his work: https://github.com/duane-r/mobs_goblins/blob/work/goblin_traps.lua
|
||||
|
||||
|
||||
minetest.register_node("mobs_goblins:mossycobble_trap", {
|
||||
minetest.register_node("goblins:mossycobble_trap", {
|
||||
description = "Messy Gobblestone",
|
||||
tiles = {"default_mossycobble.png"},
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 2, stone = 1},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
paramtype = "light",
|
||||
light_source = 4,
|
||||
light_source = 3,
|
||||
})
|
||||
|
||||
minetest.register_node("mobs_goblins:stone_with_coal_trap", {
|
||||
description = "Coal Trap",
|
||||
minetest.register_node("goblins:stone_with_coal_trap", {
|
||||
description = "Foul Coal",
|
||||
tiles = {"default_cobble.png^default_mineral_coal.png"},
|
||||
groups = {cracky = 1, level = 2},
|
||||
drop = 'default:coal_lump',
|
||||
|
@ -24,7 +25,7 @@ minetest.register_node("mobs_goblins:stone_with_coal_trap", {
|
|||
if math.random(0,100) < 10 then -- chance player will get hurt mining this
|
||||
if puncher:get_hp() > 0 then
|
||||
puncher:set_hp(puncher:get_hp()-1)
|
||||
minetest.sound_play("goblins_goblin_pick", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
minetest.sound_play("goblins_goblin_trap", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -32,7 +33,7 @@ minetest.register_node("mobs_goblins:stone_with_coal_trap", {
|
|||
|
||||
})
|
||||
|
||||
minetest.register_node("mobs_goblins:stone_with_iron_trap", {
|
||||
minetest.register_node("goblins:stone_with_iron_trap", {
|
||||
description = "Iron Gore",
|
||||
tiles = {"default_cobble.png^default_mineral_iron.png"},
|
||||
groups = {cracky = 1, level = 2},
|
||||
|
@ -44,15 +45,16 @@ minetest.register_node("mobs_goblins:stone_with_iron_trap", {
|
|||
if math.random(0,100) < 25 then -- chance player will get hurt mining this
|
||||
if puncher:get_hp() > 0 then
|
||||
puncher:set_hp(puncher:get_hp()-1)
|
||||
minetest.sound_play("goblins_goblin_pick", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
minetest.sound_play("goblins_goblin_trap", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end,
|
||||
})
|
||||
minetest.register_node("mobs_goblins:stone_with_copper_trap", {
|
||||
description = "Copper Gore",
|
||||
|
||||
minetest.register_node("goblins:stone_with_copper_trap", {
|
||||
description = "Gobber Ore",
|
||||
tiles = {"default_cobble.png^default_mineral_copper.png"},
|
||||
groups = {cracky = 1, level = 2},
|
||||
drop = 'default:copper_lump',
|
||||
|
@ -63,14 +65,15 @@ minetest.register_node("mobs_goblins:stone_with_copper_trap", {
|
|||
if math.random(0,100) < 50 then -- chance player will get hurt mining this
|
||||
if puncher:get_hp() > 0 then
|
||||
puncher:set_hp(puncher:get_hp()-1)
|
||||
minetest.sound_play("goblins_goblin_pick", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
minetest.sound_play("goblins_goblin_trap", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
minetest.register_node("mobs_goblins:stone_with_gold_trap", {
|
||||
description = "Gold Gore",
|
||||
|
||||
minetest.register_node("goblins:stone_with_gold_trap", {
|
||||
description = "Gold Shinies",
|
||||
tiles = {"default_cobble.png^default_mineral_gold.png"},
|
||||
groups = {cracky = 1,level = 2},
|
||||
drop = 'default:gold_lump',
|
||||
|
@ -81,14 +84,15 @@ minetest.register_node("mobs_goblins:stone_with_gold_trap", {
|
|||
if math.random(0,100) < 50 then -- chance player will get hurt mining this
|
||||
if puncher:get_hp() > 0 then
|
||||
puncher:set_hp(puncher:get_hp()-1)
|
||||
minetest.sound_play("goblins_goblin_pick", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
minetest.sound_play("goblins_goblin_trap", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
minetest.register_node("mobs_goblins:stone_with_diamond_trap", {
|
||||
description = "Diamond Gore",
|
||||
|
||||
minetest.register_node("goblins:stone_with_diamond_trap", {
|
||||
description = "Pretty Diamonds",
|
||||
tiles = {"default_cobble.png^default_mineral_diamond.png"},
|
||||
groups = {cracky = 1, level = 3},
|
||||
drop = 'default:diamond',
|
||||
|
@ -99,14 +103,14 @@ minetest.register_node("mobs_goblins:stone_with_diamond_trap", {
|
|||
if math.random(0,100) < 75 then -- chance player will get hurt mining this
|
||||
if puncher:get_hp() > 0 then
|
||||
puncher:set_hp(puncher:get_hp()-1)
|
||||
minetest.sound_play("goblins_goblin_pick", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
minetest.sound_play("goblins_goblin_trap", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("mobs_goblins:molten_gold_source", {
|
||||
minetest.register_node("goblins:molten_gold_source", {
|
||||
description = "Molten Gold Source",
|
||||
inventory_image = minetest.inventorycube("default_lava.png"),
|
||||
drawtype = "liquid",
|
||||
|
@ -144,8 +148,8 @@ minetest.register_node("mobs_goblins:molten_gold_source", {
|
|||
drop = "",
|
||||
drowning = 1,
|
||||
liquidtype = "source",
|
||||
liquid_alternative_flowing = "mobs_goblins:molten_gold_flowing",
|
||||
liquid_alternative_source = "mobs_goblins:molten_gold_source",
|
||||
liquid_alternative_flowing = "goblins:molten_gold_flowing",
|
||||
liquid_alternative_source = "goblins:molten_gold_source",
|
||||
liquid_viscosity = 7,
|
||||
liquid_renewable = false,
|
||||
liquid_range = 3,
|
||||
|
@ -154,7 +158,7 @@ minetest.register_node("mobs_goblins:molten_gold_source", {
|
|||
groups = {lava=3, liquid=2, hot=3, igniter=1},
|
||||
})
|
||||
|
||||
minetest.register_node("mobs_goblins:molten_gold_flowing", {
|
||||
minetest.register_node("goblins:molten_gold_flowing", {
|
||||
description = "Flowing Molten Gold",
|
||||
inventory_image = minetest.inventorycube("default_lava.png"),
|
||||
drawtype = "flowingliquid",
|
||||
|
@ -192,8 +196,8 @@ minetest.register_node("mobs_goblins:molten_gold_flowing", {
|
|||
drop = "",
|
||||
drowning = 1,
|
||||
liquidtype = "flowing",
|
||||
liquid_alternative_flowing = "mobs_goblins:molten_gold_flowing",
|
||||
liquid_alternative_source = "mobs_goblins:molten_gold_source",
|
||||
liquid_alternative_flowing = "goblins:molten_gold_flowing",
|
||||
liquid_alternative_source = "goblins:molten_gold_source",
|
||||
liquid_viscosity = 7,
|
||||
liquid_renewable = false,
|
||||
liquid_range = 3,
|
||||
|
@ -206,7 +210,7 @@ minetest.register_node("mobs_goblins:molten_gold_flowing", {
|
|||
|
||||
--[[ too bad we can't keep track of what physics are set too by other mods...]]
|
||||
minetest.register_abm({
|
||||
nodenames = {"mobs_goblins:mossycobble_trap"},
|
||||
nodenames = {"goblins:mossycobble_trap"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
|
@ -221,7 +225,7 @@ minetest.register_abm({
|
|||
end})
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"mobs_goblins:stone_with_coal_trap"},
|
||||
nodenames = {"goblins:stone_with_coal_trap"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
|
@ -243,7 +247,7 @@ minetest.register_abm({
|
|||
-- summon a metallic goblin?
|
||||
-- pit of iron razors?
|
||||
minetest.register_abm({
|
||||
nodenames = {"mobs_goblins:stone_with_iron_trap"},
|
||||
nodenames = {"goblins:stone_with_iron_trap"},
|
||||
interval = 2,
|
||||
chance = 2, --this may be a dud
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
|
@ -251,7 +255,7 @@ minetest.register_abm({
|
|||
if object:is_player() then
|
||||
if object:get_hp() > 0 then
|
||||
object:set_hp(object:get_hp()-1)
|
||||
minetest.sound_play("goblins_goblin_pick", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
minetest.sound_play("goblins_goblin_trap", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -277,7 +281,7 @@ end
|
|||
|
||||
--[[ based on dwarves cactus]]
|
||||
minetest.register_abm({
|
||||
nodenames = {"mobs_goblins:stone_with_copper_trap"},
|
||||
nodenames = {"goblins:stone_with_copper_trap"},
|
||||
interval = 1,
|
||||
chance = 2,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
|
@ -287,20 +291,20 @@ minetest.register_abm({
|
|||
object:set_hp(object:get_hp()-1)
|
||||
-- sprite
|
||||
lightning_effects(pos, 3)
|
||||
minetest.sound_play("goblins_goblin_pick", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
minetest.sound_play("goblins_goblin_trap", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
end
|
||||
end
|
||||
end
|
||||
end})
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"mobs_goblins:stone_with_gold_trap"},
|
||||
nodenames = {"goblins:stone_with_gold_trap"},
|
||||
interval = 1,
|
||||
chance = 2,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
for _,object in ipairs(minetest.get_objects_inside_radius(pos, 2)) do
|
||||
if object:is_player() then
|
||||
minetest.set_node(pos, {name="mobs_goblins:molten_gold_source"})
|
||||
minetest.set_node(pos, {name="goblins:molten_gold_source"})
|
||||
if object:get_hp() > 0 then
|
||||
object:set_hp(object:get_hp()-2)
|
||||
minetest.sound_play("default_dig_crumbly", {pos = pos, gain = 0.5, max_hear_distance = 10})
|
||||
|
@ -318,12 +322,10 @@ if setting == true then
|
|||
else
|
||||
print("enable_tnt ~= true")
|
||||
end
|
||||
|
||||
local singleplayer = minetest.is_singleplayer()
|
||||
if (not singleplayer and setting ~= true) or (singleplayer and setting == false) then
|
||||
if ( minetest.is_singleplayer() ~= true and setting ~= true) or (minetest.is_singleplayer() == true and setting == false) then
|
||||
-- wimpier trap for non-tnt settings
|
||||
minetest.register_abm({
|
||||
nodenames = {"mobs_goblins:stone_with_diamond_trap"},
|
||||
nodenames = {"goblins:stone_with_diamond_trap"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
|
@ -343,7 +345,7 @@ if (not singleplayer and setting ~= true) or (singleplayer and setting == false)
|
|||
else
|
||||
-- 5... 4... 3... 2... 1...
|
||||
minetest.register_abm({
|
||||
nodenames = {"mobs_goblins:stone_with_diamond_trap"},
|
||||
nodenames = {"goblins:stone_with_diamond_trap"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
|
@ -0,0 +1,451 @@
|
|||
local debug_goblins_announce_spawning = minetest.settings:get_bool("debug_goblins_announce_spawning") or false
|
||||
local debug_goblins_relations = minetest.settings:get_bool("debug_goblins_relations") or false
|
||||
local debug_goblins_secret = minetest.settings:get_bool("debug_goblins_secret") or false
|
||||
local debug_goblins_territories = minetest.settings:get_bool("debug_goblins_territories") or false
|
||||
local debug_goblins_territory_relations = minetest.settings:get_bool("debug_goblins_territory_relations") or false
|
||||
local debug_goblins_trade_relations = minetest.settings:get_bool("debug_goblins_trade_relations") or false
|
||||
|
||||
local announce_spawning = debug_goblins_announce_spawning
|
||||
|
||||
local S = minetest.get_translator("goblins")
|
||||
|
||||
local function print_s(input)
|
||||
print(goblins.strip_escapes(input))
|
||||
end
|
||||
|
||||
function goblins.timer(target,timer_name,timeout)
|
||||
local start = os.time()
|
||||
local t_name = timer_name
|
||||
if not t_name then t_name = default end
|
||||
if target and minetest.is_player(target) then
|
||||
local player = target
|
||||
local meta = player:get_meta()
|
||||
local timer = "timer_"..t_name
|
||||
if not meta:get_int(timer) then
|
||||
meta:set_int(timer,start)
|
||||
elseif meta:get_int(timer) and
|
||||
os.time() > (meta:get_int(timer) + timeout) then
|
||||
meta:set_int(timer,0)
|
||||
return timeout
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
goblins.gob_name_parts = {
|
||||
list_a = "Ach Adz Ak Ark Az Balg Bilg Blid Blig Blok Blot Bolg Boor Bot Bug Burk Chu Dokh Drik Driz Drub Duf Flug Gaw Gad Gag Gah Gak Gar Gat Gaz Ghag Ghak Ghor Git Glag Glak Glat Glig Gliz Glok Gnat Gog Grak Grat Guk Hig Irk Kak Kav Khad Krig Lag Lak Lig Likk Loz Luk Lun Mak Maz Miz Mog Mub Mur Nad Nag Naz Nilg Nikk Nogg Nok Nukk Nur Pog Rag Rak Rat Rok Ronk Rot Shrig Shuk Skrag Skug Slai Slig Slog Sna Snag Snark Snat Snig Snik Snit Sog Spik Stogg Tog Unk Urf Vark Vog Yad Yagg Yak Yark Yarp Yig Yip Zat Zib Zit Ziz Zob Zord",
|
||||
list_b = "ach adz ak ark awg az balg bilg blid blig blok blot bolg bot bug burk bus dokh drik driz duf ffy flug g ga gad gag gah gak gar gat gaz ghag ghak git glag glak glat glig gliz glok gnat gog grak grat gub guk hig irk kak khad krig lag lak lig likk loz luk mak maz miz mub murch nad nag naz nilg nikk nogg nok nukk og plus rag rak rat rkus rok shrig shuk skrag skug slai slig slog sna snag snark snat snig snik snit sog spik stogg thus tog un urf us vark yad yagg yak yark yarp yig yip zat zib zit ziz",
|
||||
list_opt = "ah ay e ee gah ghy y ya"
|
||||
}
|
||||
--need to find more goblinly-sounding words than these..
|
||||
goblins.words_desc = {
|
||||
tool_adj = S("bent broken crusty dirty dull favorite gnarly grubbly happy moldy pointy ragged rusty sick sharp slimy trusty"),
|
||||
motiv_adj = S("quickly quietly slowly stealthily"),
|
||||
verbs = S("eats drinks hears moves feels smells sees")
|
||||
}
|
||||
local gob_name_parts = goblins.gob_name_parts
|
||||
|
||||
--- This can build all the mobs in our mod.
|
||||
-- @gob_types is a table with the key used to build the subtype with values that are unique to that subtype
|
||||
-- @goblin_template is the table with all params that a mob type would have defined
|
||||
function goblins.generate(gob_types,goblin_template)
|
||||
for k, v in pairs(gob_types) do
|
||||
-- we need to get a fresh template to modify for every type or we get some carryover values:-P
|
||||
local g_template = table.copy(goblin_template)
|
||||
-- g_type should be different every time so no need to freshen
|
||||
local g_type = v
|
||||
for x, y in pairs(g_type) do
|
||||
-- print_s("found template modifiers " ..dump(x).." = "..dump(y))
|
||||
g_template[x] = g_type[x]
|
||||
end
|
||||
print_s("Assembling the "..g_template.description..":")
|
||||
if g_template.lore then print_s(" "..g_template.lore) end
|
||||
if g_template.additional_properties and g_template.additional_properties.goblin_tools then
|
||||
--print("found in template:"..g_template.goblin_tool)
|
||||
goblins.tool_gen(g_template.additional_properties.goblin_tools)
|
||||
end
|
||||
--print_s("resulting template: " ..dump(g_template))
|
||||
mobs:register_mob("goblins:goblin_"..k, g_template)
|
||||
mobs:register_egg("goblins:goblin_"..k, S("@1 Egg",g_template.description),"default_mossycobble.png", 1)
|
||||
g_template.spawning.name = "goblins:goblin_"..k --spawn in the name of the key!
|
||||
mobs:spawn(g_template.spawning)
|
||||
if g_template.additional_properties then
|
||||
for x,y in pairs(g_template.additional_properties) do
|
||||
minetest.registered_entities["goblins:goblin_"..k][x] = y
|
||||
end
|
||||
end
|
||||
--print(dump(minetest.registered_entities["goblins:goblin_"..k]))
|
||||
g_template = {}
|
||||
end
|
||||
end
|
||||
|
||||
--- Our mobs, territories, etc can have randomly generated names.
|
||||
-- @name_parts is the name parts table: {list_a = "foo bar baz"}
|
||||
-- @rules are the list table key names in order of how they will be chosen
|
||||
-- "-" and "\'" are rules that can be used to add a hyphen or apostrophe respectively
|
||||
function goblins.generate_name(name_parts, rules)
|
||||
-- print_s("generating name")
|
||||
local name_arrays = {}
|
||||
local r_parts = {}
|
||||
local generated_name = {}
|
||||
for k,v in pairs(name_parts) do
|
||||
-- name_arrays.k = mysplit(v)
|
||||
name_arrays.k = string.split(v," ")
|
||||
-- print_s(dump(name_arrays.k))
|
||||
r_parts[k] = k
|
||||
r_parts[k] = name_arrays.k[math.random(1,#name_arrays.k)]
|
||||
end
|
||||
--local r_parts.k = name_arrays.k[math.random(1,#name_arrays.k)] did not work
|
||||
--print_s(name_a)
|
||||
if r_parts.list_opt and math.random() <= 0.5 then r_parts.list_opt = "" end
|
||||
--print_s(r_parts.list_a..r_parts.list_b..r_parts.list_opt)
|
||||
if rules then
|
||||
--print_s(dump(rules))
|
||||
local gen_name = ""
|
||||
for i, v in ipairs(rules) do
|
||||
if v == "-" then
|
||||
gen_name = gen_name.."-"
|
||||
elseif v == "\'" then
|
||||
gen_name = gen_name.."\'"
|
||||
else
|
||||
gen_name = gen_name..r_parts[v]
|
||||
end
|
||||
end
|
||||
generated_name = gen_name
|
||||
--print_s(dump(generated_name))
|
||||
return generated_name
|
||||
else
|
||||
generated_name = r_parts.list_a..r_parts.list_b..r_parts.list_opt
|
||||
return generated_name
|
||||
end
|
||||
end
|
||||
|
||||
local function territory_list_update(player_name, territory_name)
|
||||
local known_territories = {}
|
||||
local recorded = false
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
local meta = player:get_meta()
|
||||
known_territories = minetest.deserialize(meta:get_string("territory_list"))
|
||||
if type(known_territories) == table then
|
||||
for k,v in known_territories do
|
||||
if territory_name == v then
|
||||
recorded = true
|
||||
end
|
||||
end
|
||||
else
|
||||
known_territories = {}
|
||||
--known_territories[1] = territory_name
|
||||
end
|
||||
if not recorded then
|
||||
table.insert(known_territories,territory_name)
|
||||
meta:set_string("territory_list", minetest.serialize(known_territories))
|
||||
end
|
||||
goblins.update_hud(player)
|
||||
end
|
||||
|
||||
--- This will store the name of a player that learns the mobs territory in the mobs table.
|
||||
function goblins.secret_territory(self, player_name, tell)
|
||||
local pname = player_name
|
||||
--self.nametag = self.secret_name.." of "..self.secret_territory.name
|
||||
if not self.secret_territory_told then
|
||||
self.secret_territory_told = {ix = os.time()}
|
||||
end
|
||||
if self.secret_territory_told[pname] then return self.secret_territory end
|
||||
if not self.secret_territory_told[pname] and tell then
|
||||
minetest.chat_send_player(pname,
|
||||
S(" You have learned the secret territory name of @1!!",dump(self.secret_territory.name)))
|
||||
self.secret_territory_told[pname] = os.time()
|
||||
---self.nametag = self.secret_name.." of "..self.secret_territory.name
|
||||
---player could also receive some kind of functional token for this territory
|
||||
territory_list_update(pname, self.secret_territory.name)
|
||||
return self.secret_territory
|
||||
end
|
||||
if debug_goblins_secret then
|
||||
for k,v in pairs(self.secret_territory_told) do
|
||||
print_s(self.secret_name.." revealed secret territories to: "..k.." "..v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- This will store the name of a player that learns the mobs name in the mobs table.
|
||||
function goblins.secret_name(self, player_name,tell)
|
||||
-- self.nametag = self.secret_name
|
||||
local pname = player_name
|
||||
if not self.secret_name_told then
|
||||
self.secret_name_told = {[self.secret_name] = os.time()}
|
||||
end
|
||||
if self.secret_name_told[pname] then return self.secret_name end
|
||||
if not self.secret_name_told[pname] and tell then
|
||||
--The goblin is willing to share something special!
|
||||
minetest.chat_send_player(pname,
|
||||
S(" You have learned the secret name of @1!!",self.secret_name))
|
||||
self.secret_name_told[pname] = os.time()
|
||||
--self.nametag = self.secret_name
|
||||
return self.secret_name
|
||||
end
|
||||
if debug_goblins_secret then
|
||||
for k,v in pairs(self.secret_name_told) do
|
||||
print_s(self.secret_name.." revealed secret name to: "..k.." "..v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------
|
||||
-- Announce Spawn ...summon it with care, for the floods shall come!
|
||||
-----------
|
||||
-- Purely for debugging or curiosity it can be enabled at the top of this page
|
||||
function goblins.announce_spawn(self)
|
||||
if announce_spawning == true then
|
||||
local pos = vector.round(self.object:get_pos())
|
||||
if not pos then return end
|
||||
if self.secret_name then
|
||||
print_s( self.name:split(":")[2].. ", "..self.secret_name.." spawned at: " .. minetest.pos_to_string(pos))
|
||||
else
|
||||
print_s( self.name:split(":")[2].. " spawned at: " .. minetest.pos_to_string(pos))
|
||||
end
|
||||
--goblins.territory(pos)
|
||||
if self.secret_territory then
|
||||
if self.secret_name then
|
||||
print_s(self.secret_name.. " dwells in "..self.secret_territory["name"].." at " ..self.secret_territory["vol"].."!\n" )
|
||||
else
|
||||
print_s("A nameless creature inhabits"..self.secret_territory["name"].." at " ..self.secret_territory["vol"].."!\n" )
|
||||
end
|
||||
else
|
||||
local territory = {goblins.territory(pos)}
|
||||
if self.secret_name then
|
||||
print_s(territory[1].." at "..territory[2].." festers with the lurking form of "..self.secret_name.."\n")
|
||||
else
|
||||
print_s(territory[1].." at "..territory[2].." becomses the domain of a nameless one\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-----
|
||||
-- CREATE TERRITORIES
|
||||
-----
|
||||
-- Get the Minimum of a Chunk https://forum.minetest.net/viewtopic.php?p=351592#p351592
|
||||
-- by duane » Sun Jul 14, 2019 00:20 and
|
||||
-- by TalkLounge » Sun Jul 14, 2019 11:39
|
||||
|
||||
local function mapgen_min_max(pos)
|
||||
local pos = vector.round(pos)
|
||||
local chunksize = tonumber(type(minetest.settings) ~= "nil" and minetest.settings:get("chunksize") or minetest.setting_get("chunksize")) or 5
|
||||
local chunk_offset = math.floor(chunksize / 2) * 16
|
||||
local csize = {x = chunksize * 16, y = chunksize * 16, z = chunksize * 16}
|
||||
local chunk = vector.floor(vector.divide(vector.add(pos, chunk_offset), csize))
|
||||
local minp = vector.add(vector.multiply(chunk, 80), -chunk_offset)
|
||||
local maxp = vector.add(minp, (chunksize * 16) - 1)
|
||||
return minp, maxp
|
||||
end
|
||||
|
||||
-- refer to https://rubenwardy.com/minetest_modding_book/en/map/storage.html
|
||||
local goblins_db_fields = goblins_db:to_table()["fields"]
|
||||
|
||||
local function goblins_db_deser(table)
|
||||
local data = minetest.deserialize(goblins_db_fields[table])
|
||||
return data
|
||||
end
|
||||
|
||||
local function goblins_db_read(table)
|
||||
local data = minetest.deserialize(goblins_db:to_table()["fields"][table])
|
||||
return data
|
||||
end
|
||||
|
||||
local function goblins_db_write(key, table)
|
||||
local data = minetest.serialize(table)
|
||||
|
||||
goblins_db:set_string(key, data)
|
||||
return key, data
|
||||
end
|
||||
|
||||
function goblins.territory_test(pos,territories)
|
||||
|
||||
local db_test = minetest.serialize({fieldtest = "initialized"})
|
||||
print_s("\nBEGIN EXISTING LIST--------\n"..dump(goblins_db_read("territories")).."\n ------END LIST\n")
|
||||
end --test
|
||||
|
||||
-- Provides a way to take a chunks position and use it a base for storing information in a mod.
|
||||
-- it is dependant on the mapgen_min_max function above as well the goblins_db functions for storage.
|
||||
-- @opt_data is just for adding information to this territories storage it expects a table
|
||||
function goblins.territory(pos, opt_data)
|
||||
-- this should be called on spawn but before a goblin gets its secret name
|
||||
-- a handy chunk name key generator, should create a unique name for every chunk
|
||||
local function cat_pos(chunk)
|
||||
return "Xa"..chunk[1].x.."_Ya"..chunk[1].y.."_Za"..chunk[1].z.."_x_Xb"..chunk[2].x.."_Yb"..chunk[2].y.."_Zb"..chunk[2].z
|
||||
end
|
||||
-- get list of known territories and thier chunks or
|
||||
local existing_territories = {}
|
||||
existing_territories = goblins_db_read("territories")
|
||||
local minp_maxp = {mapgen_min_max(pos)}
|
||||
local this_territory = {}
|
||||
local volume_cat_pos = cat_pos(minp_maxp)
|
||||
--print_s(dump(volume_cat_pos).." cat paws!")
|
||||
if debug_goblins_territories then
|
||||
print_s("\n----Known territories")
|
||||
for k,v in pairs(existing_territories) do
|
||||
print_s(dump(k).." is known as "..dump(existing_territories[k].name))
|
||||
end
|
||||
print_s("----End Known territories\n")
|
||||
end
|
||||
local territories_table = table.copy(existing_territories)
|
||||
-- print_s(dump(territories_table).."copied territories")
|
||||
-- print_s("\nTERRITORY TEST TABLE READ:\n" ..dump(goblins_db_read("territories")).."\n")
|
||||
if territories_table[volume_cat_pos] then
|
||||
local t_vol = volume_cat_pos
|
||||
local t_name = territories_table[volume_cat_pos]["name"]
|
||||
if opt_data then --insert a table
|
||||
for k,v in pairs(opt_data) do
|
||||
--if not territories_table[volume_cat_pos][k] -- this is tricky...
|
||||
territories_table[volume_cat_pos][k] = v
|
||||
local territories_table_ser = minetest.serialize(territories_table)
|
||||
goblins_db:set_string("territories", territories_table_ser )
|
||||
if debug_goblins_territories then
|
||||
print_s(k.." added to "..territories_table[volume_cat_pos]["name"])
|
||||
end
|
||||
--end
|
||||
end
|
||||
return t_name, t_vol
|
||||
end
|
||||
if debug_goblins_territories then
|
||||
print_s(dump(t_name).." at "..dump(t_vol).." is already known!")
|
||||
end
|
||||
-- print_s(dump(territories_table[volume_cat_pos]).. "\n ---end details \n")
|
||||
return t_name, t_vol
|
||||
else
|
||||
-- generate a name for this territory
|
||||
local name_rules = {"list_a","list_opt","-","list_b"}
|
||||
local territory_name = goblins.generate_name(gob_name_parts,name_rules)
|
||||
-- print_s(dump(territory_name).." is a name whispered among those who dwell here")
|
||||
-- set concatenated minp_maxp as the key for this territory and populate data
|
||||
-- print_s(dump(volume_cat_pos)))
|
||||
this_territory[(volume_cat_pos)] = {
|
||||
["name"] = territory_name,
|
||||
["flag"] = pos,
|
||||
}
|
||||
if debug_goblins_territories then
|
||||
print_s("The territory of "..dump(this_territory[volume_cat_pos]["name"]).. " at "..volume_cat_pos.." will be recorded.")
|
||||
end
|
||||
territories_table[volume_cat_pos] = this_territory[volume_cat_pos]
|
||||
-- print_s(dump(territories_table).. " is the new table \n")
|
||||
-- print_s("\nTERRITORY TESTING SERIALIZED WRITE:\n"..dump(this_territory_ser).."\n")
|
||||
-- prepare the territories_table for storage, unless we have something else to say..
|
||||
if opt_data then --insert a table
|
||||
for k,v in pairs(opt_data) do
|
||||
--if not territories_table[volume_cat_pos][k] -- this is tricky...
|
||||
territories_table[volume_cat_pos][k] = v
|
||||
local territories_table_ser = minetest.serialize(territories_table)
|
||||
goblins_db:set_string("territories", territories_table_ser )
|
||||
if debug_goblins_territories then
|
||||
print_s(k.." added to "..territories_table[volume_cat_pos]["name"])
|
||||
end
|
||||
--end
|
||||
end
|
||||
local t_name = territory_name
|
||||
local t_vol = volume_cat_pos
|
||||
return t_name, t_vol
|
||||
end
|
||||
local territories_table_ser = minetest.serialize(territories_table)
|
||||
goblins_db:set_string("territories", territories_table_ser )
|
||||
local t_name = territory_name
|
||||
local t_vol = volume_cat_pos
|
||||
return t_name, t_vol
|
||||
end
|
||||
--print_s("\nTERRITORY TEST:\n"..dump(this_territory.name).."\n")
|
||||
end
|
||||
|
||||
-- Express and optionally store the relationship between a mob and a player or another mob.
|
||||
-- Will return all known relationships if nothing is defined.
|
||||
-- @self will return only relations know to that mob
|
||||
-- @target_name will return the table of the self.relations (mobs) relations to the target if
|
||||
-- optional target_table is not defined.
|
||||
-- @target_table will set the value of a mobs relation to the target.
|
||||
-- THIS SCRIPT IS DEPENDANT on secret_name and secret_territory!
|
||||
function goblins.relations(self, target_name, target_table)
|
||||
local existing_relations = {}
|
||||
if not goblins_db_read("relations") then
|
||||
print_s("relations DB not initialized from init.lua!!")
|
||||
return
|
||||
end
|
||||
-- let's get all the facts, this query may have to get more specific if its too big...
|
||||
local existing_relations = goblins_db_read("relations")
|
||||
-- do we want to know something in particular?
|
||||
|
||||
if self then
|
||||
local name = self.secret_name
|
||||
--have we started keeping track of who we know?
|
||||
if not self["relations"] then
|
||||
self.relations = {ix = os.time()}
|
||||
if debug_goblins_relations then print_s("self table: "..dump(self)) end
|
||||
-- create an entry for ourselves with our territory as the value
|
||||
if self.secret_name and self.secret_territory then
|
||||
self.relations[name] = self.secret_territory.name
|
||||
existing_relations[name] = self.relations
|
||||
if debug_goblins_relations then print_s("self table updated: "..dump(self.relations).."\n") end
|
||||
if debug_goblins_relations then print_s("adding mob to relations table: "..dump(existing_relations[self]).."\n")end
|
||||
goblins_db_write("relations",existing_relations)
|
||||
end
|
||||
end
|
||||
-- do we just want to know how we feel about the target?
|
||||
if target_name and not target_table then
|
||||
-- do we even know the target? If not, initialize relationship root for target
|
||||
if not self.relations[target_name] then
|
||||
self.relations[target_name] = {ix = os.time()}
|
||||
existing_relations[name] = self.relations
|
||||
goblins_db_write("relations",existing_relations)
|
||||
end
|
||||
return self.relations[target_name]
|
||||
end
|
||||
-- we have something to say about the target!
|
||||
if target_name and target_table then
|
||||
-- mob adds it to their entity..
|
||||
for k,v in pairs(target_table) do
|
||||
self.relations[target_name][k] = v
|
||||
end
|
||||
|
||||
existing_relations[name] = self.relations
|
||||
-- we add or modify this relationship in the mod storage "relations"
|
||||
|
||||
--existing_relations[name][target_name] = target_value
|
||||
--print_s(dump(existing_relations))
|
||||
goblins_db_write("relations",existing_relations)
|
||||
if debug_goblins_relations then print_s("updated self table: "..dump(self.relations).."\n") end
|
||||
return existing_relations[target_name]
|
||||
end
|
||||
end
|
||||
-- we dont have a target just dump everything known about everone
|
||||
if debug_goblins_relations then print_s("all relations"..dump(existing_relations).."\n") end
|
||||
return existing_relations
|
||||
end
|
||||
|
||||
--- Returns the status of a players relation throughout a territory
|
||||
-- will initialize any new relation if required
|
||||
-- at some point to support an array of relations to return
|
||||
function goblins.relations_territory(self, player_name, rel_name)
|
||||
local pname = player_name
|
||||
local relations = goblins.relations(self)
|
||||
local t_relation = 0
|
||||
-- initialize tables if necessary
|
||||
if not self["relations"] then self.relations = {ix = os.time()} end
|
||||
if not self.relations[pname] then goblins.relations(self, pname) end
|
||||
if not self.relations[pname][rel_name] then self.relations[pname][rel_name] = 0 end
|
||||
--be sure that relations have been started with player before using this!
|
||||
if debug_goblins_trade_relations then print_s(S("Individual mob trade relations: ")) end
|
||||
for m_name,prop in pairs(relations) do
|
||||
if self.secret_territory.name == relations[m_name][m_name] and
|
||||
relations[m_name][pname] and relations[m_name][pname][rel_name] then
|
||||
--add up the trade relations between the player and all goblins in this goblins territory
|
||||
t_relation = t_relation + relations[m_name][pname][rel_name]
|
||||
if debug_goblins_trade_relations then print_s(S("@1 = @2",m_name,relations[m_name][pname][rel_name]))end
|
||||
end
|
||||
end
|
||||
if debug_goblins_territory_relations then
|
||||
print_s("this mob's relation are "..dump(relations[self.secret_name]))
|
||||
print_s(S("@1 territory @2 relation score = @3",self.secret_territory.name,rel_name,t_relation))
|
||||
end
|
||||
return t_relation
|
||||
end
|
||||
|
||||
function goblins.player_relations_territory(player,territory)
|
||||
end
|
||||
|