Wielding and rewards

master
francisco athens 2020-07-16 17:09:30 -07:00
parent a9bc1412b5
commit cb4382d2f2
10 changed files with 460 additions and 135 deletions

31
README.md Normal file
View File

@ -0,0 +1,31 @@
# [witches] Witches (Mobs Redo addon) [mod] for Minetest
Witches is copyright 2020 Francisco Athens, Ramona Athens, Damon Athens and Simone Athens
The MIT License (MIT)
* code :https://gitlab.com/freelikegnu/witches
## 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
## Licenses of Source Media Files:
* witches_witch.b3d and witch.blend
* copyright 2020 Francisco Athens, Ramona Athens, Damon Athens and Simone 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
* witches_*.png files and witches_*.xcf files
* copyright 2020 Francisco Athens, Ramona Athens, Damon Athens and Simone Athens
Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
* http://creativecommons.org/licenses/by-sa/3.0/
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/

138
init.lua
View File

@ -1,11 +1,14 @@
--Witches is copyright 2020 Francisco Athens, Ramona Athens, Damon Athens and Simone Athens
--The MIT License (MIT)
--local mod_name = "witches"
local path = minetest.get_modpath("witches")
witches = {}
witches.version = "20200611"
witches.version = "20200716"
print("this is Witches "..witches.version)
-- Strips any kind of escape codes (translation, colors) from a string
-- https://github.com/minetest/minetest/blob/53dd7819277c53954d1298dfffa5287c306db8d0/src/util/string.cpp#L777
function witches.strip_escapes(input)
@ -43,58 +46,13 @@ local S = minetest.get_translator("witches")
local witches_version = witches.version
dofile(path .. "/utilities.lua")
dofile(path .. "/ui.lua")
dofile(path .. "/items.lua")
print("enter the witches! version: "..witches.version)
local witch_hat = {}
witch_hat = {
initial_properties = {
--physical = true,
pointable = false,
collisionbox = {0,0,0,0,0,0},
visual = "mesh",
mesh = "witches_witch-hat.b3d",
visual_size = {x = 1, y = 1, z = 1},
textures = {"witches_witch_hat.png"},
},
message = "Default message",
on_step = function(self)
if not self.owner or not self.owner:get_luaentity() then
self.object:remove()
else
-- local owner_head_bone = self.owner:get_luaentity().head_bone
-- local position,rotation = self.owner:get_bone_position(owner_head_bone)
-- self.object:set_attach(self.owner, owner_head_bone, vector.new(0,0,0), rotation)
end
end
}
minetest.register_entity("witches:witch_hat",witch_hat)
local witch_tool = {}
witch_tool = {
initial_properties = {
--physical = true,
pointable = false,
collisionbox = {0,0,0,0,0,0},
visual = "wielditem",
visual_size = {x = 0.3, y = 0.3},
wield_item = "default:stick",
--inventory_image = "default_tool_woodpick.png",
},
message = "Default message",
on_step = function(self)
if not self.owner or not self.owner:get_luaentity() then
self.object:remove()
end
end
}
minetest.register_entity("witches:witch_tool",witch_tool)
local variance = witches.variance
local rnd_color = witches.rnd_color
local rnd_colors = witches.rnd_colors
local hair_colors = witches.hair_colors
local spawning = {
generic = {
@ -119,23 +77,6 @@ local witch_types = {
}
local rnd_colors = {"none", "red","green","blue","orange","yellow","violet","cyan"}
local hair_colors = {"black","brown","blonde","gray","red","blue","green"}
local hat_bling = {"band","feather","veil"}
local function rnd_color(rnd_colors)
local color = rnd_colors[math.random(1,#rnd_colors)]
return color
end
local function color_mod_string()
local str = "^[colorize:\""..rnd_color(rnd_colors)..":50\""
return str
end
--for rng of small floats
local function variance(min,max)
local target = math.random(min,max) / 100
print(target)
return target
end
local witch_template = { --your average witch,
description = "Basic Witch",
@ -216,10 +157,9 @@ local witch_template = { --your average witch,
"default:blueberries", "default:torch", "default:stick",
"flowers:mushroom_brown","flowers:mushroom_red"
},
on_rightclick = function(self,clicker)
local pname = clicker:get_player_name()
witches.guessing.show_to(self, pname)
on_rightclick = function(self,clicker)
witches.quests(self,clicker)
end,
on_spawn = function(self)
@ -233,7 +173,7 @@ local witch_template = { --your average witch,
self.speed_mod = math.random(-1, 1)
end
print("speed mod: "..self.speed_mod)
--print("speed mod: "..self.speed_mod)
--rng for testing variants
if not self.size then
self.size = {x = variance(90,100), y = variance(75,105), z = variance(90,100)}
@ -270,9 +210,20 @@ local witch_template = { --your average witch,
self.object:set_texture_mod("^witches_skin"..self.skin..".png^witches_accessories.png^witches_witch_hair_"..self.hair_color..".png")
end
if not self.secret_name then
self.secret_name = witches.generate_name(witches.name_parts_female).." the "..self.color_mod
self.secret_name = witches.generate_name(witches.name_parts_female)
end
print(self.secret_name.." has spawned")
if not self.secret_title then
self.secret_title = witches.generate_name(witches.words_desc, {"titles"})
end
if not self.secret_locale then
self.secret_locale = witches.generate_name(witches.name_parts_female, {"syllablesStart","syllablesEnd"})
end
self.item_request = witches.generate_name(witches.quest_dialogs, {"item_request"})
--print(self.secret_name.." has spawned")
--print("self: "..dump(self.follow))
-- print("self properties "..dump(self.object:get_properties()))
witches.looking_for(self)
@ -284,47 +235,12 @@ local witch_template = { --your average witch,
after_activate = function(self)
--maddest hatter <|%\D
self.head_bone = "Head"
local hat = minetest.add_entity(self.object:get_pos(), "witches:witch_hat")
hat:set_attach(self.object, "Head", vector.new(0,4,0), vector.new(0,180,0))
local hat_ent = hat:get_luaentity()
hat_ent.owner = self.object
print("HAT: "..dump(hat_ent))
local he_props = hat_ent.object:get_properties()
--print("he props: "..dump(he_props))
local hat_size = variance(90, 120)
local hat_mods = ""
for i,v in pairs(hat_bling) do
if v == "veil" and math.random() < 0.1 then
hat_mods = hat_mods.."^witches_witch_hat_"..v..".png"
else
if v ~= "veil" and math.random() < 0.5 then
hat_mods = hat_mods.."^witches_witch_hat_"..v..".png"
end
end
end
self.hat_mods = hat_mods
print("hat_mods: "..self.hat_mods)
if self.color_mod ~= "none" then
hat_ent.object:set_texture_mod("^[colorize:"..self.color_mod..":60"..self.hat_mods)
else
if self.hat_mods then hat_ent.object:set_texture_mod(self.hat_mods) end
end
he_props.visual_size.y = hat_size
print("he props: "..dump(he_props))
hat_ent.object:set_properties(he_props)
local tool = minetest.add_entity(self.object:get_pos(), "witches:witch_tool")
tool:set_attach(self.object, "Arm_Right", {x=0.3, y=4.0, z=2}, {x=-100, y=225, z=90})
tool:get_luaentity().owner = self.object
witches.attach_hat(self,"witches:witch_hat")
witches.attach_tool(self,"witches:witch_tool")
end,
}
--- This can build all the mobs in our mod.
-- @witch_types is a table with the key used to build the subtype with values that are unique to that subtype
-- @witch_template is the table with all params that a mob type would have defined

96
items.lua Normal file
View File

@ -0,0 +1,96 @@
--Witches is copyright 2020 Francisco Athens, Ramona Athens, Damon Athens and Simone Athens
--The MIT License (MIT)
local variance = witches.variance
local rnd_color = witches.rnd_color
local rnd_colors = witches.rnd_colors
local hat_bling = {"band","feather","veil"}
local witch_hat = {}
witch_hat = {
initial_properties = {
--physical = true,
pointable = false,
collisionbox = {0,0,0,0,0,0},
visual = "mesh",
mesh = "witches_witch-hat.b3d",
visual_size = {x = 1, y = 1, z = 1},
textures = {"witches_witch_hat.png"},
},
message = "Default message",
on_step = function(self)
if not self.owner or not self.owner:get_luaentity() then
self.object:remove()
else
-- local owner_head_bone = self.owner:get_luaentity().head_bone
-- local position,rotation = self.owner:get_bone_position(owner_head_bone)
-- self.object:set_attach(self.owner, owner_head_bone, vector.new(0,0,0), rotation)
end
end
}
minetest.register_entity("witches:witch_hat",witch_hat)
local witch_tool = {}
witch_tool = {
initial_properties = {
--physical = true,
pointable = false,
collisionbox = {0,0,0,0,0,0},
visual = "wielditem",
visual_size = {x = 0.3, y = 0.3},
wield_item = "default:stick",
--inventory_image = "default_tool_woodpick.png",
},
on_step = function(self)
if not self.owner or not self.owner:get_luaentity() then
self.object:remove()
end
end
}
minetest.register_entity("witches:witch_tool",witch_tool)
function witches.attach_hat(self,item)
self.head_bone = "Head"
local item = item or "witches:witch_hat"
local hat = minetest.add_entity(self.object:get_pos(), item)
hat:set_attach(self.object, "Head", vector.new(0,4.5,0), vector.new(0,180,0))
local hat_ent = hat:get_luaentity()
hat_ent.owner = self.object
--print("HAT: "..dump(hat_ent))
local he_props = hat_ent.object:get_properties()
--print("he props: "..dump(he_props))
local hat_size = variance(90, 120)
local hat_mods = ""
for i,v in pairs(hat_bling) do
if v == "veil" and math.random() < 0.1 then
hat_mods = hat_mods.."^witches_witch_hat_"..v..".png"
else
if v ~= "veil" and math.random() < 0.5 then
hat_mods = hat_mods.."^witches_witch_hat_"..v..".png"
end
end
end
self.hat_mods = hat_mods
--print("hat_mods: "..self.hat_mods)
if self.color_mod ~= "none" then
hat_ent.object:set_texture_mod("^[colorize:"..self.color_mod..":60"..self.hat_mods)
else
if self.hat_mods then hat_ent.object:set_texture_mod(self.hat_mods) end
end
he_props.visual_size.y = hat_size
--print("he props: "..dump(he_props))
hat_ent.object:set_properties(he_props)
end
function witches.attach_tool(self,item)
item = item or "witches:witch_tool"
local tool = minetest.add_entity(self.object:get_pos(), item)
tool:set_attach(self.object, "Arm_Right", {x=0.3, y=4.0, z=2}, {x=-100, y=225, z=90})
tool:get_luaentity().owner = self.object
end

21
license.txt Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
copyright (c) 2020 Francisco Athens, Ramona Athens, Damon Athens and Simone Athens
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

69
ui.lua
View File

@ -1,21 +1,29 @@
--Witches is copyright 2020 Francisco Athens, Ramona Athens, Damon Athens and Simone Athens
--The MIT License (MIT)
local function print_s(input)
print(witches.strip_escapes(input))
end
local S = minetest.get_translator("witches")
witches.guessing = {}
function witches.guessing.get_formspec(self,name)
-- TODO: display whether the last guess was higher or lower
witches.find_item_quest = {}
witches.found_item_quest = {}
local item_request = witches.generate_name(witches.quest_dialogs, {"item_request"})
function witches.find_item_quest.get_formspec(self,name)
-- retrieve the thing
local quest_item = witches.looking_for(self)
local text = S("My name is @1 and I'm looking for:\n@2",self.secret_name,quest_item.desc)
witches.item_quest(self)
local text = S("My name is @1, @2 of @3. @4 @5?",self.secret_name,self.secret_title,self.secret_locale,self.item_request,quest_item.desc)
self.item_request = nil
local formspec = {
"formspec_version[3]",
"size[7,3]",
"label[0.375,0.5;", minetest.formspec_escape(text), "]",
"item_image[3,0.75;1,1;"..quest_item.name.. "]"
"size[6,3,true]",
"position[0.5,0.7]",
"anchor[0.5,0.5]",
--"bgcolor[red]",
"textarea[0.25,0.25;5.5,1.25;;;", minetest.formspec_escape(text), "]",
"item_image[2.5,1.5;1,1;"..quest_item.name.. "]"
--[[
"field[0.375,1.25;5.25,0.8;number;Number;]",
"button[1.5,2.3;3,0.8;guess;Guess]"
@ -27,6 +35,45 @@ function witches.guessing.get_formspec(self,name)
end
function witches.guessing.show_to(self,name)
minetest.show_formspec(name, "witches.guessing:game", witches.guessing.get_formspec(self,name))
function witches.found_item_quest.get_formspec(self,name)
local display_item = ""
-- retrieve the thing
local quest_item = witches.looking_for(self)
local text = S("Thank you @1, for finding @2!",name,quest_item.desc)
--print(dump(self.players[name].reward_text))
if self.players[name].reward_text then
text = text.."\n("..self.players[name].reward_text .. "!)"
end
if self.players[name].reward_item then
display_item = self.players[name].reward_item
else
display_item = quest_item.name
end
local formspec = {
"formspec_version[3]",
"size[6,3.5,true]",
"position[0.5,0.7]",
"anchor[0.5,0.5]",
"textarea[0.25,0.25;5.5,2;;;", minetest.formspec_escape(text), "]",
"item_image[2.5,2.25;1,1;"..display_item.. "]"
--[[
"field[0.375,1.25;5.25,0.8;number;Number;]",
"button[1.5,2.3;3,0.8;guess;Guess]"
--]]
}
-- table.concat is faster than string concatenation - `..`
return table.concat(formspec, "")
end
function witches.find_item_quest.show_to(self,name)
minetest.show_formspec(name, "witches.find_item_quest:game", witches.find_item_quest.get_formspec(self,name))
end
function witches.found_item_quest.show_to(self,clicker)
local name = clicker:get_player_name()
minetest.show_formspec(name, "witches.found_item_quest:game", witches.found_item_quest.get_formspec(self,name))
self.players[name].reward_item = nil
self.players[name].reward_text = nil
end

View File

@ -1,3 +1,5 @@
--Witches is copyright 2020 Francisco Athens, Ramona Athens, Damon Athens and Simone Athens
--The MIT License (MIT)
local function print_s(input)
print(witches.strip_escapes(input))
end
@ -16,10 +18,136 @@ witches.name_parts_female = {
syllablesEnd = "ba, beth, da, kira, laith, lle, ma, mina, mira, na, nn, nne, nor, ra, rin, ssra, ta, th, tha, thra, tira, tta, vea, vena, we, wen, wyn",
}
--- 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
witches.words_desc = {
tool_adj = S("shiny, polished, favorite, beloved, cherished"),
titles = S("artificer, librarian, logician, sorcerant, thaumaturgist, polymorphist, elementalist, hedge, herbologist, arcanologist, tutor, historian, mendicant, restorationist"),
}
witches.quest_dialogs = {
item_request = S("Can you retrieve, Would you happen to have, Would you kindly retrieve, Might you please return with, Do you know I seek only, Have you but one, Why must my task require, Is it so difficult to find, Wherefor art, Must there be but a few, Could I trouble you for")
}
witches.rnd_colors = {"none", "red","green","blue","orange","yellow","violet","cyan","pink","black","magenta","grey"}
witches.hair_colors = {"black","brown","blonde","gray","red","blue","green"}
local rnd_color = witches.rnd_color
local rnd_colors = witches.rnd_colors
function witches.rnd_color(rnd_colors)
local color = rnd_colors[math.random(1,#rnd_colors)]
return color
end
function witches.color_mod_string()
local str = "^[colorize:\""..rnd_color(rnd_colors)..":50\""
return str
end
--for rng of small floats
function witches.variance(min,max)
local target = math.random(min,max) / 100
--print(target)
return target
end
function witches.item_quest(self)
if not self.item_request then
self.item_request = witches.generate_name(witches.quest_dialogs, {"item_request"})
return self.item_request
end
end
--- Drops a special personlized item
function witches.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:getpos()
pos.y = pos.y + 0.5
--witches.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()
--boost the stats!
local capabilities = stack:get_tool_capabilities()
for x,y in pairs(capabilities) do
if x == "groupcaps" then
for a,b in pairs(y) do
--print(dump(a).." is "..dump(b).."\n---")
if b and b.uses then
print("original uses: "..capabilities.groupcaps[a].uses)
capabilities.groupcaps[a].uses = b.uses + 10
print("boosted uses: "..capabilities.groupcaps[a].uses)
--print(dump(a).." is now "..dump(b))
end
if b and b.times then
for i,v in pairs(b.times) do
if v > 0.3 then
print("original time:".. v )
local v_rnd = math.random(1,3) / 10
v = v - v_rnd
print("boosted time:".. v )
end
capabilities.groupcaps[a].times[i] = v
end
end
end
elseif x == "damage_groups" then
for a,b in pairs(y) do
--print(dump(a.." = "..capabilities.damage_groups[a]))
capabilities.damage_groups[a] = b + 1
--print(dump(capabilities.damage_groups[a]))
end
end
end
meta:set_tool_capabilities(capabilities)
--print (dump(capabilities))
local tool_adj = witches.generate_name(witches.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()
local reward_text = S("@1 drops @2",self.secret_name, meta:get_string("description"))
--print("generated text: "..reward_text)
local reward_item = stack:get_name()
--print("generated:"..stack:get_name())
local rewards = {r_text = reward_text, r_item = reward_item}
return rewards
end
end
end
end
end
function witches.attachment_check(self)
if not self.owner or not self.owner:get_luaentity() then
@ -31,20 +159,106 @@ function witches.attachment_check(self)
end
end
function witches.looking_for(self)
if self.follow then
local item = self.follow[math.random(1,#self.follow)]
--local stack = ItemStack({name = item})
function witches.found_item(self,clicker)
local item = clicker:get_wielded_item()
if item and item:get_name() == self.item_quest.name then
local pname = clicker:get_player_name()
if not minetest.settings:get_bool("creative_mode") then
item:take_item()
clicker:set_wielded_item(item)
end
local find = {name = minetest.registered_items[item].name, desc = minetest.registered_items[item].description, icon = minetest.registered_items[item].inventory_image}
--local meta = item:get_meta()
print_s(S(dump(desc)))
print(dump(find))
return find
if not self.players then
self.players = {}
--print("no records")
end
if not self.players[pname] then
self.players[pname] = {}
--print("no records 2")
end
--print(dump(self.players))
if not self.players[pname].favors then
self.players[pname] = { favors = 0 }
end
self.players[pname].favors = self.players[pname].favors + 1
local reward = {}
print(self.secret_name.." has now received 2 favors"..self.players[pname].favors.." from " ..pname)
--if self.players[pname].favors >=3 and math.fmod(18, self.players[pname].favors) == 0 then
reward = witches.special_gifts(self,pname)
--print(reward_text)
if reward and reward.r_text then
self.players[pname].reward_text = reward.r_text
end
if reward and reward.r_item then
-- print("reward: "..reward.r_item)
self.players[pname].reward_item = reward.r_item
end
-- end
witches.found_item_quest.show_to(self, clicker)
self.item_quest = nil
return item
end
end
function witches.quests(self, clicker)
local pname = clicker:get_player_name()
--print(pname.." clicked on a witch!")
local item = clicker:get_wielded_item()
local pos = clicker:getpos()
mobs:yaw_to_pos(self, pos)
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
--print("we are holding a "..dump(item:get_name()))
if not self.item_quest or item:get_name() ~= self.item_quest.name then
--print("we should start a quest")
witches.find_item_quest.show_to(self, pname)
-- print(self.secret_name.." wants a ".. self.item_quest.name)
elseif self.item_quest and item and item:get_name() == self.item_quest.name then
--print(self.item_quest.name.." and "..item:get_name())
witches.found_item(self,clicker)
end
end
function witches.looking_for(self)
if not self.item_quest then
if self.follow then
local item = self.follow[math.random(1,#self.follow)]
--local stack = ItemStack({name = item})
local find = {name = minetest.registered_items[item].name, desc = minetest.registered_items[item].description, icon = minetest.registered_items[item].inventory_image}
--local meta = item:get_meta()
--print_s(S(dump(desc)))
--print(dump(find))
self.item_quest = find
return self.item_quest
end
else
return self.item_quest
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 witches.generate_name(name_parts, rules)
-- print_s("generating name")
local name_arrays = {}