Add player stats, add bucket textures, more progress on entity system

This commit is contained in:
IamPyu 2024-10-24 17:48:58 -06:00
parent ca753d2803
commit 88dd7aa48c
11 changed files with 192 additions and 37 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
})

View 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)

View File

@ -0,0 +1 @@
depends = pyutest_tools,pyutest_player

View File

@ -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)

View 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
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 B

BIN
textures/pyutest-bucket.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

BIN
textures/pyutest-rune.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B