Add player stats, add bucket textures, more progress on entity system
This commit is contained in:
parent
ca753d2803
commit
88dd7aa48c
@ -12,6 +12,10 @@
|
||||
- New lily pad texture
|
||||
- Add Time Device, it is not craftable in Survival mode and is only for Creative mode.
|
||||
- Improve death messages
|
||||
- Added stats which can improve your defense and attack capabilities
|
||||
- Defense stat is only applied when your health is greater than one fourth of it!
|
||||
- Added upgrade runes which can be used to improve your defense and attack stats
|
||||
|
||||
|
||||
## [Oct 19th 2024] Bugfix Update
|
||||
|
||||
|
@ -25,6 +25,8 @@ PyuTest.NODEBOX_DEFAULT = {
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
}
|
||||
|
||||
PyuTest.WORLD_GRAVITY = 10
|
||||
|
||||
PyuTest.get_schem_path = function (name)
|
||||
return minetest.get_modpath("pyutest") .. "/schematics/"..name..".mts"
|
||||
end
|
||||
|
@ -6,22 +6,33 @@ PATH_FIND_ALGORITHM = "Dijkstra"
|
||||
PyuTest.ENTITY_BLOOD_AMOUNT = 6
|
||||
PyuTest.HUMAN_LIKE_CBOX = {-0.25, -1, -0.25, 0.25, 1, 0.25}
|
||||
|
||||
PyuTest.get_nearest_entity = function (self, pos, range, only_player)
|
||||
PyuTest.get_nearest_entity = function (entity, pos, range, only_player)
|
||||
local closet_distance = math.huge
|
||||
local nearest
|
||||
|
||||
local function set_nearest_and_distance(n, d)
|
||||
nearest = n
|
||||
closet_distance = d
|
||||
end
|
||||
|
||||
for obj in minetest.objects_inside_radius(pos, range) do
|
||||
local dist = vector.distance(pos, obj:get_pos())
|
||||
|
||||
if dist < closet_distance and obj ~= self then
|
||||
if dist < closet_distance and obj ~= entity then
|
||||
if only_player then
|
||||
if obj:is_player() then
|
||||
closet_distance = dist
|
||||
nearest = obj
|
||||
set_nearest_and_distance(obj, dist)
|
||||
end
|
||||
else
|
||||
closet_distance = dist
|
||||
nearest = obj
|
||||
local e = obj:get_luaentity()
|
||||
-- Ignore items
|
||||
if e then
|
||||
if e.name ~= "__builtin:item" then
|
||||
set_nearest_and_distance(obj, dist)
|
||||
end
|
||||
else
|
||||
set_nearest_and_distance(obj, dist)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -65,35 +76,45 @@ PyuTest.register_entity_spawn = function (name, entity, def)
|
||||
minetest.remove_node(pos)
|
||||
|
||||
local min = def.min or 1
|
||||
local max = def.max or 3
|
||||
local max = def.max or 1
|
||||
|
||||
for _ = min, math.random(min, max) do
|
||||
if max == 1 then
|
||||
minetest.add_entity(pos, entity)
|
||||
else
|
||||
for _ = min, math.random(min, max) do
|
||||
minetest.add_entity(pos, entity)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
local function do_physics(luaentity, cfg, moveresult)
|
||||
local obj = luaentity.object
|
||||
local data = luaentity.data
|
||||
local class = {}
|
||||
|
||||
function class:do_physics()
|
||||
local obj = self.object
|
||||
local data = self.data
|
||||
local cfg = self.options
|
||||
local moveresult = self.moveresult
|
||||
local pos = obj:get_pos()
|
||||
|
||||
|
||||
if cfg.gravity then
|
||||
if not moveresult.touching_ground then
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function path_find_nearest_entity(luaentity, cfg, dtime, player)
|
||||
local obj = luaentity.object
|
||||
local data = luaentity.data
|
||||
function class:path_find_nearest_entity(follow_only_player)
|
||||
local obj = self.object
|
||||
local data = self.data
|
||||
local cfg = self.options
|
||||
local pos = obj:get_pos()
|
||||
|
||||
if data.target.path == nil then
|
||||
data.target.object = PyuTest.get_nearest_entity(obj, pos, cfg.sight_range, player)
|
||||
data.target.object = PyuTest.get_nearest_entity(obj, pos, cfg.sight_range, follow_only_player)
|
||||
|
||||
if data.target.object == nil then
|
||||
return
|
||||
@ -110,13 +131,14 @@ local function path_find_nearest_entity(luaentity, cfg, dtime, player)
|
||||
data.target.pathindex = nil
|
||||
else
|
||||
local p = data.target.path[data.target.pathindex]
|
||||
obj:set_velocity(p * dtime)
|
||||
obj:set_yaw(vector.angle(data.target.object:get_pos(), obj:get_pos()))
|
||||
-- obj:set_velocity(p * dtime)
|
||||
obj:move_to(p, true)
|
||||
data.target.pathindex = data.target.pathindex + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
PyuTest.make_mob = function (name, properties, options)
|
||||
local default_options = {
|
||||
ai = "dummy",
|
||||
@ -148,7 +170,7 @@ PyuTest.make_mob = function (name, properties, options)
|
||||
|
||||
local collisionbox = properties.collisionbox or PyuTest.HUMAN_LIKE_CBOX
|
||||
|
||||
minetest.register_entity(name, {
|
||||
minetest.register_entity(name, setmetatable({
|
||||
initial_properties = PyuTest.util.tableconcat(properties, {
|
||||
hp_max = properties.hp_max or 20,
|
||||
physical = true,
|
||||
@ -170,12 +192,16 @@ PyuTest.make_mob = function (name, properties, options)
|
||||
},
|
||||
|
||||
on_step = function (self, dtime, moveresult)
|
||||
self.dtime = dtime
|
||||
self.moveresult = moveresult
|
||||
|
||||
local ai = self.options.ai
|
||||
local obj = self.object
|
||||
local p = obj:get_properties()
|
||||
|
||||
|
||||
local hp = obj:get_hp()
|
||||
if cfg.health_regen and not (hp >= p.hp_max) then
|
||||
if self.options.health_regen and not (hp >= p.hp_max) then
|
||||
obj:set_hp(hp + 0.5)
|
||||
end
|
||||
|
||||
@ -190,16 +216,16 @@ PyuTest.make_mob = function (name, properties, options)
|
||||
return
|
||||
end
|
||||
|
||||
do_physics(self, cfg, moveresult)
|
||||
self:do_physics()
|
||||
|
||||
if ai == "follownearest" then
|
||||
path_find_nearest_entity(self, cfg, dtime, true)
|
||||
self:path_find_nearest_entity(false)
|
||||
end
|
||||
end,
|
||||
|
||||
on_punch = function (self)
|
||||
local pos = self.object:get_pos()
|
||||
minetest.sound_play(cfg.sounds.hurt, {pos = pos})
|
||||
minetest.sound_play(self.options.sounds.hurt, {pos = pos})
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount = 8,
|
||||
@ -224,9 +250,9 @@ PyuTest.make_mob = function (name, properties, options)
|
||||
on_death = function (self)
|
||||
local pos = self.object:get_pos()
|
||||
|
||||
for _, v in pairs(cfg.drops) do
|
||||
for _, v in pairs(self.options.drops) do
|
||||
minetest.add_item(pos, v)
|
||||
end
|
||||
end
|
||||
})
|
||||
}, {__index = class}))
|
||||
end
|
||||
|
@ -12,6 +12,7 @@ PyuTest.make_mob("pyutest_entities:test_follower", {
|
||||
}, {
|
||||
ai = "follownearest",
|
||||
max_jump = 1,
|
||||
max_drop = 50,
|
||||
view_range = 3,
|
||||
|
||||
drops = {
|
||||
@ -28,12 +29,3 @@ PyuTest.make_mob("pyutest_entities:dummy", {
|
||||
},
|
||||
nametag = "Dummy",
|
||||
}, {})
|
||||
|
||||
PyuTest.register_entity_spawn("pyutest_entities:dummy_spawner", "pyutest_entities:dummy", {
|
||||
min = 1,
|
||||
max = 5,
|
||||
|
||||
place_on = {"group:ground"},
|
||||
y_max = PyuTest.OVERWORLD_TOP,
|
||||
y_min = PyuTest.OVERWORLD_SURFACE_BOTTOM
|
||||
})
|
||||
|
31
mods/ITEMS/pyutest_upgrades/init.lua
Normal file
31
mods/ITEMS/pyutest_upgrades/init.lua
Normal file
@ -0,0 +1,31 @@
|
||||
PyuTest.make_upgrade_rune = function (name, desc, stat, increase, max)
|
||||
PyuTest.make_item(name, desc, {
|
||||
upgrade_rune = 1,
|
||||
}, "pyutest-rune.png", {
|
||||
color = color,
|
||||
on_use = function (itemstack, user, pointed_thing)
|
||||
if not user then return end
|
||||
if not user:is_player() then return end
|
||||
|
||||
local value = PyuTest.get_player_stat(user, stat)
|
||||
|
||||
if value == max then
|
||||
return
|
||||
end
|
||||
|
||||
-- Stat value below 1 causes problems
|
||||
if (value + increase) < 1 then
|
||||
return
|
||||
end
|
||||
|
||||
PyuTest.set_player_stat(user, stat, value + increase)
|
||||
|
||||
minetest.sound_play({name = "spellbook_action", gain = 0.75}, {pos = user:get_pos()})
|
||||
itemstack:take_item()
|
||||
return itemstack
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
PyuTest.make_upgrade_rune("pyutest_upgrades:defense", "Defense Upgrade Rune", "defense", 0.5, 5)
|
||||
PyuTest.make_upgrade_rune("pyutest_upgrades:attack", "Attack Upgrade Rune", "attack", 0.5, 3)
|
1
mods/ITEMS/pyutest_upgrades/mod.conf
Normal file
1
mods/ITEMS/pyutest_upgrades/mod.conf
Normal file
@ -0,0 +1 @@
|
||||
depends = pyutest_tools,pyutest_player
|
@ -1,10 +1,11 @@
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
dofile(modpath.."/stats.lua")
|
||||
|
||||
-- player setup
|
||||
minetest.register_on_joinplayer(function (player)
|
||||
if player == nil then return end
|
||||
local name = player:get_player_name()
|
||||
player:set_properties({
|
||||
hp_max = 25
|
||||
})
|
||||
|
||||
player:get_inventory():set_width("main", 8)
|
||||
player:get_inventory():set_size("main", 8 * 4)
|
||||
|
98
mods/PLAYER/pyutest_player/stats.lua
Normal file
98
mods/PLAYER/pyutest_player/stats.lua
Normal file
@ -0,0 +1,98 @@
|
||||
PyuTest.DEFAULT_PLAYER_STATS = {
|
||||
attack = 1,
|
||||
defense = 1,
|
||||
}
|
||||
|
||||
PyuTest.get_player_stats = function (player)
|
||||
local meta = player:get_meta()
|
||||
return minetest.deserialize(meta:get("stats") or minetest.serialize(PyuTest.DEFAULT_PLAYER_STATS))
|
||||
end
|
||||
|
||||
PyuTest.save_player_stats = function (player, stats)
|
||||
local meta = player:get_meta()
|
||||
meta:set_string("stats", minetest.serialize(stats))
|
||||
end
|
||||
|
||||
PyuTest.set_player_stat = function(player, stat, value)
|
||||
local stats = PyuTest.get_player_stats(player)
|
||||
stats[stat] = value
|
||||
PyuTest.save_player_stats(player, stats)
|
||||
end
|
||||
|
||||
PyuTest.get_player_stat = function(player, stat)
|
||||
local stats = PyuTest.get_player_stats(player)
|
||||
return stats[stat]
|
||||
end
|
||||
|
||||
minetest.register_on_player_hpchange(function (player, hp_change, reason)
|
||||
local max_hp = player:get_properties().hp_max
|
||||
local current_hp = player:get_hp()
|
||||
local new_hp_change = hp_change
|
||||
|
||||
if new_hp_change >= 0 then
|
||||
return new_hp_change
|
||||
end
|
||||
|
||||
if reason.type == "punch" then
|
||||
local obj = reason.object
|
||||
|
||||
if obj and obj:is_player() then
|
||||
local attack = PyuTest.get_player_stat(obj, "attack")
|
||||
new_hp_change = new_hp_change * attack
|
||||
end
|
||||
end
|
||||
|
||||
minetest.log(new_hp_change)
|
||||
|
||||
if current_hp > (max_hp / 4) then
|
||||
local defense = PyuTest.get_player_stat(player, "defense")
|
||||
-- new_hp_change = new_hp_change * (1 / defense)
|
||||
new_hp_change = new_hp_change / defense
|
||||
new_hp_change = math.floor(new_hp_change + 0.5)
|
||||
end
|
||||
|
||||
minetest.log(new_hp_change)
|
||||
|
||||
return new_hp_change
|
||||
end, true)
|
||||
|
||||
minetest.register_on_joinplayer(function (player)
|
||||
if player == nil then return end
|
||||
|
||||
-- This saves the default stats if none exist.
|
||||
PyuTest.save_player_stats(player, PyuTest.get_player_stats(player))
|
||||
end)
|
||||
|
||||
minetest.register_chatcommand("setstat", {
|
||||
params = "<stat> <value> [<player>]",
|
||||
privs = {
|
||||
give = 1
|
||||
},
|
||||
description = "Set the value of PLAYER's player stat STAT to VALUE",
|
||||
func = function (name, param)
|
||||
local split = param:split(" ")
|
||||
local statname = split[1]
|
||||
local value = tonumber(split[2])
|
||||
local player = split[3] or name
|
||||
|
||||
-- Stat value below 1 causes problems
|
||||
if value < 1 then
|
||||
value = 1
|
||||
end
|
||||
|
||||
PyuTest.set_player_stat(minetest.get_player_by_name(player), statname, value)
|
||||
return true, string.format("Set stat %s value to %s", statname, tostring(value))
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("getstat", {
|
||||
params = "<stat> [<player>]",
|
||||
description = "Gets the value of PLAYER's player stat: STAT",
|
||||
func = function (name, param)
|
||||
local split = param:split(" ")
|
||||
local statname = split[1]
|
||||
local player = split[2] or name
|
||||
local stat = PyuTest.get_player_stat(minetest.get_player_by_name(player), statname)
|
||||
return true, string.format("%s of %s: %s", statname, player, tostring(stat or 0))
|
||||
end
|
||||
})
|
BIN
textures/pyutest-bucket-overlay.png
Normal file
BIN
textures/pyutest-bucket-overlay.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 94 B |
BIN
textures/pyutest-bucket.png
Normal file
BIN
textures/pyutest-bucket.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 149 B |
BIN
textures/pyutest-rune.png
Normal file
BIN
textures/pyutest-rune.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 196 B |
Loading…
x
Reference in New Issue
Block a user