Compare commits

...

10 Commits

Author SHA1 Message Date
Jo5629
72a1173cc6 Updates. 2024-10-11 17:37:04 -04:00
Jo5629
65a90718ae Update stalker.lua 2024-10-10 20:05:22 -04:00
Jo5629
3478f214ce Update mod.conf 2024-10-10 19:58:55 -04:00
Jo5629
23324e25e1 Preparations. 2024-10-10 19:56:49 -04:00
Jo5629
5bb690a51a Updates. 2024-09-28 13:37:19 -04:00
Jo5629
353e1fa934 Prepare for release. 2024-09-05 19:25:26 -04:00
Jo5629
40884e7fa9 Update README.md 2024-08-20 20:15:29 -04:00
Jo5629
2e065045b0 Update api.lua 2024-08-20 20:08:10 -04:00
Jo5629
1f64dd9728 Updates. 2024-08-20 19:56:21 -04:00
Jo5629
aaa11a9e01 Updates. 2024-08-18 18:00:22 -04:00
26 changed files with 383 additions and 119 deletions

View File

@ -44,6 +44,11 @@ herobrine_settings.register_setting("stalking_timer", {
- `tbl` should be an array.
- `index` is an numerical index from an array.
- `val` is the value found using `tbl[index]`.
- `herobrine_settings.random(min, max, num)` - Returns `num` or `boolean`.
- Pretty much equivalent to `math.random()`, but uses `PcgRandom` for a stronger randomness.
- `min, max` are integers.
- `num` can be any number.
- If `num` is not `nil`, it returns a boolean based on if the number generated in the `min, max` range is less than or equal to `num`.
- `herobrine_settings.get_setting_val_from_day_count(name, days)` - Returns `val, success`
- Calculated the output from a specific setting.
- `name` is a string, but must be a valid setting name, whether hidden or not.
@ -75,9 +80,14 @@ print(success) --> true
- `herobrine_ambience.unregister_sound(name)` - Unregisters a sound. Returns `true` for success and `false` for failure.
- `herobrine_ambience.get_ambience_list()` - Get all the registered sounds.
- `herobrine_ambience.get_random_sound()` - Gets a random sound from the registered list.
- `herobrine_ambience.play_sound(sound_name, duration)` - Plays sound `sound_name` for `duration` seconds. Returns `sound` and `job`, respectively.
- `herobrine_ambience.play_sound(spec, duration, parameters)` - Returns `sound` and `job`, respectively.
- Plays a sound for `duration` seconds.
- `spec` - Can be a `SimpleSoundSpec` table or just a sound name.
- `parameters` - A sound parameter table.
- `sound` - a handle returned by `minetest.sound_play`
- `job` - Returns a job table from `minetest.after`
- `herobrine_ambience.fade_sound(handle, step, gain)` - Returns a boolean.
- Inputs are the same as `minetest.sound_fade`.
## Herobrine Signs API
@ -89,7 +99,7 @@ print(success) --> true
- Uses the setting `signs_spawnable_on`.
- Returns an **AIR NODE** that is **ONE BLOCK** above the original position.
- `herobrine.signs.place_sign(pos, text)` - Places a sign at `pos` with `text` as a string on it.
- Supports `sign_lib`.
- Supports `signs_lib`.
**EXAMPLE:**
@ -161,14 +171,13 @@ The command can then be accessed using `/herobrine save_settings`.
- `herobrine.register_on_day_change(function(daycount))`
- Called when the **internal** daycount has changed.
- `daycount` is a number.
- `herobrine.register_on_spawn(function(name, pos))`
- `herobrine.register_on_spawn(function(luaentity))`
- Called when a Herobrine mob is spawned.
- `name` can be any of these types: `"herobrine:herobrine", "herobrine:herobrine_footsteps", "herobrine:herobrine_stalker"`.
- `pos` is a position where the mob was spawned at.
- `luaentity` is a table.
- Must return `true` otherwise the mob will not spawn.
- `herobrine.register_on_despawn(function(name, pos))`
- `herobrine.register_on_despawn(function(luaentity))`
- Called when a Herobrine mob has been despawned.
- `name` and `pos` are the same like in `herobrine.register_on_spawn`.
- `luaentity` is a table.
## In the Fog API Variables

View File

@ -2,20 +2,20 @@
# In the Fog
*Herobrine* has entered Minetest. **BEWARE and TREAD LIGHTLY.**
*Herobrine* has entered Minetest. **BEWARE** and **TREAD LIGHTLY.**
## WARNINGS
- Bugs and crashes should be expected.
- This is why using the latest commit from the repository in your world is not recommended. Please use the stable versions in the releases.
- This mod is more focused towards singleplayer.
- Multiplayer is functional, but bugs not found in singleplayer testing might appear in multiplayer.
- Parts of the mod are able to crash your game **AT RANDOM.**
- Parts of the mod are also able to cause permanent damage to your world.
- This mod is more singleplayer-focused and is mostly tested in singleplayer.
- Multiplayer is functional, but bugs not found in singleplayer testing may appear in multiplayer.
- ~~Parts of the mod are purposefully able to crash your game **AT RANDOM.**~~ (This has been disabled till further notice.)
- Parts of the mod are also able to cause damage to your world.
## HELP
- `/herobrine help`: Shows a list of commands within the mod. Some may be hidden from view.
- `/herobrine help [true]`: Shows a list of commands within the mod. Some may be hidden from view.
- `herobrine_admin`: A privilege needed to execute special commands.
- `/herobrine settings`: Shows a formspec with all of the registered settings and their values.
- You need `herobrine_admin` in order to update those settings and experience their effect.
@ -23,4 +23,7 @@
[In the Fog API Documentation](https://github.com/Jo5629/jo5629-In_the_Fog/blob/main/DOCUMENTATION.md)
**INSPIRATION:** [Lunar Eclipse Studios - From the Fog](https://lunareclipse.studio/creations/from-the-fog) and [Calvin's From the Fog Series](https://www.youtube.com/@Calvin9000).
### INSPIRATION
- [Lunar Eclipse Studios - From the Fog](https://lunareclipse.studio/creations/from-the-fog)
- [Calvin's From the Fog Series](https://www.youtube.com/@Calvin9000)

View File

@ -1,7 +1,13 @@
local version = "v3.0.1"
local srcpath = minetest.get_modpath(minetest.get_current_modname()) .. "/src"
herobrine = {}
local version = "v2.0.0-dev"
local srcpath = minetest.get_modpath(minetest.get_current_modname()) .. "/src"
if not minetest.get_modpath("herobrine_awards") then
herobrine_awards = {
unlock = function() end
}
end
minetest.register_privilege("herobrine_admin", {
description = "Allows the player to use advanced commands with the In the Fog mod.",
@ -33,8 +39,6 @@ dofile(srcpath .. "/mobs/stalker.lua")
dofile(srcpath .. "/mobs/herobrine.lua")
dofile(srcpath .. "/mobs/footsteps.lua")
--[[ Tests.
dofile(srcpath .. "/tests.lua")
]]
--dofile(srcpath .. "/tests.lua")
minetest.log("action", "[In the Fog] Mod initialized. VERSION: " .. version)

View File

@ -1,3 +1,3 @@
name = herobrine
depends = mobs, herobrine_settings, herobrine_ambience, default, fire, doors, herobrine_commands
optional_depends = lightning, signs_lib
optional_depends = lightning, signs_lib, herobrine_awards

View File

@ -42,7 +42,7 @@ herobrine_commands.register_subcommand("ambience :word", {
local duration = math.random(20, 25)
if word == "*random" then
local sound = herobrine_ambience.get_random_sound()
herobrine_ambience.play_ambience(sound, duration)
herobrine_ambience.play_sound(sound, duration)
return true, string.format("Playing ambience sound: %s", sound)
end
local found = false
@ -54,7 +54,7 @@ herobrine_commands.register_subcommand("ambience :word", {
end
end
if found then
herobrine_ambience.play_ambience(word, duration)
herobrine_ambience.play_sound(word, duration)
return true, string.format("Playing ambience sound: %s", word)
else
minetest.chat_send_player(name, table.concat(herobrine_ambience.get_ambience_list(), ","))

View File

@ -4,7 +4,7 @@ local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer >= interval and enabled then
if math.random(1, 100) <= chance then
if herobrine_settings.random(1, 100, chance) then
minetest.request_shutdown("ANOMALY FOUND. SHUTTING DOWN WORLD IMMEDIATELY.", false, 0)
end
end

View File

@ -8,6 +8,8 @@ end
function herobrine.set_day_count(num)
herobrine_daycount = num
storage:set_int("herobrine.daycount", num)
herobrine.registered_on_day_change:RunCallbacks(false, herobrine_daycount)
end
local old_day = minetest.get_day_count()
@ -15,14 +17,13 @@ local function check_daycount()
local new_day = minetest.get_day_count()
if new_day ~= old_day then
herobrine.set_day_count(herobrine_daycount + 1)
herobrine.registered_on_day_change:RunCallbacks(false, herobrine_daycount)
old_day = new_day
end
minetest.after(15, check_daycount)
minetest.after(4, check_daycount)
end
minetest.after(0, function()
minetest.log("action", "[In the Fog] Internal daycount on server startup: " .. tostring(herobrine.get_day_count()))
old_day = minetest.get_day_count()
check_daycount()
end)

View File

@ -17,7 +17,7 @@ minetest.register_abm({
catch_up = true,
action = function(pos, node, active_object_count, active_object_count_wider)
local chance = herobrine_settings.get_setting_val_from_day_count("random_door_opening", herobrine.get_day_count())
if not (math.random(1, 100) <= chance) then return end
if not herobrine_settings.random(1, 100, chance) then return end
local status = doors.door_toggle(pos, node, nil)
if status then
minetest.log("action", string.format("[In the Fog] Door at %s was toggled.", minetest.pos_to_string(pos, 1)))

View File

@ -36,13 +36,13 @@ function herobrine.signs.generate_random_text(lang)
if not words_table[lang] or not lang then
lang = "en"
end
return words_table[lang][math.random(1, #words_table[lang])], true
return words_table[lang][herobrine_settings.random(1, #words_table[lang])], true
end
--> Took and updated the function from herobrine.find_position_near()
function herobrine.signs.find_position_near(pos, radius)
if not radius or radius > 70 then --> As long as the radius is <= 79 we will be okay. Lower the bar a little more to be safe.
radius = math.random(40, 60)
radius = herobrine_settings.random(40, 60)
end
local pos1 = {x = pos.x - radius, y = pos.y - radius, z = pos.z - radius}
local pos2 = {x = pos.x + radius, y = pos.y + radius, z = pos.z + radius}
@ -134,15 +134,14 @@ minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer >= interval then
timer = 0
if not enabled or not math.random(1, 100) <= chance then
if not enabled or not herobrine_settings.random(1, 100, chance) then
return
end
local players = {}
for _, playerobj in pairs(minetest.get_connected_players()) do
table.insert(players, playerobj:get_player_name())
end
local randpname = players[math.random(1, #players)]
local randpname = players[herobrine_settings.random(1, #players)]
local randpobj = minetest.get_player_by_name(randpname)
if randpobj then
local pos, found = herobrine.signs.find_position_near(randpobj:get_pos())
@ -150,5 +149,6 @@ minetest.register_globalstep(function(dtime)
herobrine.signs.place_sign(pos, herobrine.signs.generate_random_text())
end
end
timer = 0
end
end)

View File

@ -7,8 +7,6 @@ local function num_mese(pos)
return #nodes
end
local interval = herobrine_settings.get_setting("shrine_interval")
local old_time = storage:get_int("herobrine:shrine_gametime") or interval
minetest.register_node("herobrine:shrine_node", {
description = "Node used for the Herobrine shrine",
tiles = {"default_coal_block.png"},
@ -16,11 +14,16 @@ minetest.register_node("herobrine:shrine_node", {
groups = {cracky = 3},
sounds = default.node_sound_stone_defaults(),
on_ignite = function(pos, igniter)
local time_left = minetest.get_gametime() - old_time
if not (time_left >= interval) then
minetest.chat_send_player(igniter:get_player_name(), string.format("[In the Fog] Shrine cooldown is not over. %d seconds left.", interval - time_left))
local interval = herobrine_settings.get_setting("shrine_interval")
local old_time = storage:get_int("herobrine:shrine_gametime")
local name = igniter:get_player_name()
local time_left = (old_time - minetest.get_gametime()) * -1
if not (old_time == 0 or time_left > interval) then
minetest.chat_send_player(name, string.format("[In the Fog] %d seconds left.", interval - time_left))
return
end
local flame_pos = {x = pos.x, y = pos.y + 1, z = pos.z}
local node_name = minetest.get_node(flame_pos).name
if num_mese(pos) == 9 and node_name == "air" then

View File

@ -1,29 +1,53 @@
function herobrine.spawnHerobrine(name, pos)
if not herobrine.registered_on_spawn:RunCallbacks(true, name, pos) then
return false
end
return true, mobs:add_mob(pos, {
local luaentity = mobs:add_mob(pos, {
name = name,
ignore_count = true,
})
if not herobrine.registered_on_spawn:RunCallbacks(true, luaentity) then
luaentity.object:remove()
return false
end
return true, luaentity
end
function herobrine.despawnHerobrine(luaentity)
herobrine.registered_on_despawn:RunCallbacks(false, luaentity.name, luaentity.object:get_pos())
herobrine.registered_on_despawn:RunCallbacks(false, luaentity)
mobs:remove(luaentity)
end
local jobs = {}
herobrine._spawned = false --> Only change this if you know what you are doing.
herobrine.register_on_spawn(function(name, pos)
herobrine.register_on_spawn(function(luaentity)
if herobrine._spawned then
return false
end
herobrine._spawned = true
local sound, job = herobrine_ambience.play_sound({
name = herobrine_ambience.get_random_sound(),
max_hear_distance = herobrine_settings.random(65, 80),
pos = luaentity.object:get_pos(),
fade = 0.1,
}, herobrine_settings.random(20, 25), {
gain = 2.0,
})
luaentity.sound_id = sound
jobs[sound] = job
return true
end)
herobrine.register_on_despawn(function(name, pos)
herobrine.register_on_despawn(function(luaentity)
if herobrine._spawned then
herobrine._spawned = false
end
local id = luaentity.sound_id
herobrine_ambience.fade_sound(id, 0.1, 0)
if jobs[id] then
jobs[id]:cancel()
jobs[id] = nil
end
end)

View File

@ -23,7 +23,7 @@ end
function herobrine.find_position_near(pos, radius)
if not radius or radius > 70 then --> As long as the radius is <= 79 we will be okay. Lower the bar a little more too be safe.
radius = math.random(40, 60)
radius = herobrine_settings.random(40, 60)
end
local min = herobrine_settings.get_setting("despawn_radius") + 10
local outside = minetest.get_node_light(pos, 0.5) == 15
@ -72,23 +72,23 @@ minetest.register_globalstep(function(dtime)
local temp_chance = chance
timer = timer + dtime
if (minetest.get_timeofday() * 24) >= 20 and chance ~= 0 then --> Try some weighted chance.
local time = minetest.get_timeofday() * 24
if (time >= 20 or time <= 4) and chance ~= 0 then --> Try some weighted chance.
temp_chance = chance + 25
end
if timer >= herobrine_settings.get_setting("stalking_timer") then
timer = 0
if not math.random(1, 100) <= temp_chance then
if not herobrine_settings.random(1, 100, temp_chance) then
return
end
local players = minetest.get_connected_players()
local player = players[math.random(1, #players)]
local player = players[herobrine_settings.random(1, #players)]
local name = player:get_player_name()
local pos = herobrine.find_position_near(player:get_pos())
if minetest.pos_to_string(pos, 1) ~= minetest.pos_to_string(player:get_pos(), 1) then
herobrine.stalk_player(name, pos)
end
timer = 0
end
end)

View File

@ -14,7 +14,7 @@ minetest.register_globalstep(function(dtime)
local ppos = player:get_pos()
local pos1, pos2 = vector.add(ppos, 10), vector.subtract(ppos, 10)
for _, pos in pairs(minetest.find_nodes_in_area(pos1, pos2, "group:torch")) do
if math.random(1, 100) <= chance then
if herobrine_settings.random(1, 100, chance) then
minetest.dig_node(pos)
minetest.log("action", "[In the Fog] Removed the torch at: " .. minetest.pos_to_string(pos, 1))
end

View File

@ -15,8 +15,8 @@ local def = {
jump = true,
makes_footstep_sound = true,
sounds = {},
walk_velocity = 1.3,
run_velocity = 3,
walk_velocity = 4,
run_velocity = 6,
pushable = true,
view_range = 150,
fear_height = 0,
@ -38,7 +38,7 @@ local def = {
on_spawn = function(self)
self.despawn_timer = 0
if math.random(1, 5) <= 1 then
if herobrine_settings.random(1, 5, 1)then
local props = self.object:get_properties()
props.show_on_minimap = true
self.object:set_properties(props)
@ -48,7 +48,7 @@ local def = {
self.despawn_timer = self.despawn_timer + dtime
local object = self.object
if self.despawn_timer >= 30 then
if math.random(1, 10) <= 1 then
if herobrine_settings.random(1, 10, 1) then
herobrine.lightning_strike(object:get_pos())
end
herobrine.despawnHerobrine(self)
@ -58,7 +58,7 @@ local def = {
local objs = minetest.get_objects_inside_radius(object:get_pos(), 3)
for _, obj in pairs(objs) do
if obj:is_player() then
if math.random(1, 10) <= 1 then
if herobrine_settings.random(1, 1000, 1) then
herobrine.lightning_strike(object:get_pos())
end
herobrine.despawnHerobrine(self)
@ -78,19 +78,18 @@ minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer >= interval then
timer = 0
if not math.random(1, 100) <= chance then
if not herobrine_settings.random(1, 100, chance) then
return
end
local players = minetest.get_connected_players()
local randplayer = players[math.random(1, #players)]
local randplayer = players[herobrine_settings.random(1, #players)]
local pos, success = herobrine.find_position_near(randplayer:get_pos(), math.random(25, 35))
local pos, success = herobrine.find_position_near(randplayer:get_pos(), herobrine_settings.random(25, 35))
if success then
herobrine.spawnHerobrine("herobrine:herobrine_footsteps", pos)
end
timer = 0
end
end)
@ -111,7 +110,7 @@ local function footsteps_player(pname, target, waypoint)
if targetobj then
local ppos = targetobj:get_pos()
ppos.y = ppos.y + 1
local pos, success = herobrine.find_position_near(ppos, math.random(25, 35))
local pos, success = herobrine.find_position_near(ppos, herobrine_settings.random(25, 35))
if success then
if not herobrine.spawnHerobrine("herobrine:herobrine_footsteps", pos) then
return false, "A Herobrine has already been spawned."
@ -136,7 +135,7 @@ end
herobrine_commands.register_subcommand("footsteps_player", {
privs = herobrine_commands.default_privs,
hidden = true,
--description = "Stalks yourself. If waypoint is true, wherever Herobrine is spawned at will be marked.",
description = "Spawns Footsteps Herobrine. If waypoint is true, wherever Herobrine is spawned at will be marked.",
func = function(name)
return footsteps_player(name, name)
end,
@ -144,15 +143,16 @@ herobrine_commands.register_subcommand("footsteps_player", {
herobrine_commands.register_subcommand("footsteps_player :waypoint", {
privs = herobrine_commands.default_privs,
--description = "Stalks yourself. If waypoint is true, wherever Herobrine is spawned at will be marked.",
description = "Spawns Footsteps Herobrine. If waypoint is true, wherever Herobrine is spawned at will be marked.",
func = function(name, waypoint)
return footsteps_player(name, name, waypoint)
end
})
--[[
herobrine_commands.register_subcommand("footsteps_player :target :waypoint", {
privs = herobrine_commands.default_privs,
--description = "Stalks a player. If waypoint is true, wherever Herobrine is spawned at will be marked.",
description = "Spawns . If waypoint is true, wherever Herobrine is spawned at will be marked.",
func = function(name, target, waypoint)
local player = minetest.get_player_by_name(target)
if player then
@ -161,4 +161,5 @@ herobrine_commands.register_subcommand("footsteps_player :target :waypoint", {
return false, "Unable to find " .. target .. "."
end
end,
})
})
]]

View File

@ -1,25 +1,32 @@
local def = {
type = "monster", --> --> Somehow an npc-type mob will not despawn but a monster-type will???.
type = "monster", --> Somehow an npc-type mob will not despawn but a monster-type will???.
passive = false,
attack_type = "dogfight",
--[[
shoot_interval = 0.2,
dogshoot_switch = 2,
dogshoot_count_max = 2,
dogshoot_count2_max = 6,
arrow = "herobrine:fireball",
shoot_offset = 2,
]]
pathfinding = true,
hp_min = 300,
hp_max = 300,
hp_min = 200,
hp_max = 200,
armor = 100,
damage = 15,
damage = 12,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.8,0.35},
visual = "mesh",
mesh = "herobrine.b3d",
textures = {"herobrine.png"},
jump = true,
fly = true,
makes_footstep_sound = true,
sounds = {},
walk_velocity = 1.3,
run_velocity = 7,
walk_velocity = 4,
run_velocity = 6,
pushable = true,
view_range = 150,
fear_height = 0,
fall_damage = 0,
knock_back = false,
animation = {
speed_normal = 30,
@ -35,36 +42,143 @@ local def = {
},
glow = 4,
fire_damage = 0,
fear_height = 0,
fall_damage = 0,
on_spawn = function(self)
self.despawn_timer = 0
self.texture_timer = 0
self.invisible = false
end,
on_die = function(self, pos)
herobrine.lightning_strike(pos)
mobs:boom(self, pos, 5, 5, nil)
return false
end,
do_custom = function(self, dtime)
local object = self.object
self.despawn_timer = self.despawn_timer + dtime
if self.despawn_timer >= herobrine_settings.get_setting("despawn_timer") then
herobrine.lightning_strike(self.object:get_pos())
if self.despawn_timer > 240 then
herobrine.lightning_strike(object:get_pos())
herobrine.despawnHerobrine(self)
return false
end
self.texture_timer = self.texture_timer + dtime
if self.texture_timer >= 4 then
local props = object:get_properties()
if not self.invisible then
props.textures = {"herobrine_footsteps.png"}
else
props.textures = {"herobrine.png"}
end
self.invisible = not self.invisible
object:set_properties(props)
self.texture_timer = 0
end
end,
}
mobs:register_mob("herobrine:herobrine", def)
mobs:register_egg("herobrine:herobrine", "Spawn Herobrine", "herobrine_spawn_egg.png", 0, false)
local randmessages = {
"I " .. minetest.colorize("#FF0000", "will") .. " return.",
"Imagine dying to " .. minetest.colorize("#FF0000", "me") .. ".",
"Nice try ... But you " .. minetest.colorize("#FF0000", "failed") .. ".",
}
local function despawnHerobrine(luaentity, pos)
herobrine.lightning_strike(pos)
herobrine.despawnHerobrine(luaentity)
minetest.chat_send_all(minetest.format_chat_message("Herobrine", randmessages[herobrine_settings.random(1, #randmessages)]))
herobrine.set_day_count(0)
end
--> Despawn Herobrine after he kills a player.
minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
local luaentity = hitter:get_luaentity()
if player:get_hp() > 0 and player:get_hp() - damage <= 0 and luaentity.name == "herobrine:herobrine" and minetest.is_player(player) then --> From https://github.com/appgurueu/deathlist/blob/master/main.lua#L242
minetest.after(2, function()
herobrine.lightning_strike(hitter:get_pos())
herobrine.despawnHerobrine(luaentity)
minetest.chat_send_all(minetest.format_chat_message("Herobrine", "I will return."))
herobrine.set_day_count(0)
end)
if player:get_hp() > 0 and player:get_hp() - damage <= 0 and minetest.is_player(player) and luaentity then --> From https://github.com/appgurueu/deathlist/blob/master/main.lua#L242
if luaentity.name == "herobrine:herobrine" then
minetest.after(2, function()
despawnHerobrine(luaentity, hitter:get_pos())
end)
end
end
end)
end)
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer >= herobrine_settings.get_setting("herobrine_hunting_interval") then
if herobrine_settings.random(1, 100, herobrine_settings.get_setting_val_from_day_count("herobrine_angry_meter", herobrine.get_day_count())) then
local players = minetest.get_connected_players()
local randplayer = players[herobrine_settings.random(1, #players)]
local pos, success = herobrine.find_position_near(randplayer:get_pos())
if success then
herobrine.spawnHerobrine("herobrine:herobrine", pos)
end
end
timer = 0
end
end)
--[[
local function find_luaentity(entity)
local found, luaentity = false, nil
for _, v in pairs(minetest.luaentities) do
if tostring(v.object) == entity then
found, luaentity = true, v
break
end
end
return found, luaentity
end
local count = 0
local function spawn_lightning(pos)
local time = minetest.get_timeofday() * 24
if time >= 20 or time <= 4 then
count = count + 1
if count > 3 then
herobrine.lightning_strike(pos)
count = 0
end
end
end
mobs:register_arrow("herobrine:fireball", {
collisionbox = {-1, -1, -1, 1, 1, 1},
visual = "sprite",
visual_size = {x = 2.5, y = 2.5},
textures = {"fireball.png"},
velocity = 85,
tail = 1,
tail_texture = "smoke.png",
glow = 12,
hit_player = function(self, player)
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = math.random(4, 6)}
}, nil)
spawn_lightning(player:get_pos())
mobs:boom(self, player:get_pos(), 2, 3, nil)
end,
hit_mob = function(self, player)
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = math.random(4, 6)}
}, nil)
spawn_lightning(player:get_pos())
mobs:boom(self, player:get_pos(), 2, 3, nil)
end,
hit_node = function(self, pos, node)
spawn_lightning(pos)
mobs:boom(self, pos, 2, 3, nil)
self.object:remove()
end,
})
]]

View File

@ -12,35 +12,54 @@ local def = {
hp_min = 300,
hp_max = 300,
damage = 100,
walk_velocity = 0,
run_velocity = 0,
walk_velocity = 4,
run_velocity = 6,
pushable = true,
fly = true,
view_range = 150,
fear_height = 0,
fall_damage = 0,
knock_back = false,
makes_footstep_sound = true,
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 189, --200
punch_end = 198 --219
},
immune_to = {"all"},
glow = 4,
fall_speed = -6000,
on_spawn = function(self)
self.disable_falling = true
self.despawn_timer = 0
self.staring_timer = 0
self.texture_timer = 0
self.invisible = false
local pos = {}
if self.facing_pname == nil then
local players = minetest.get_connected_players()
pos = players[math.random(1, #players)]:get_pos()
local randplayer = players[herobrine_settings.random(1, #players)]
pos = randplayer:get_pos()
self.facing_pname = randplayer:get_player_name()
else
local player = minetest.get_player_by_name(self.facing_pname)
pos = player:get_pos()
end
self:yaw_to_pos(pos, 0)
self.herobrine_ambience = herobrine_ambience.play_ambience(herobrine_ambience.get_random_sound(), math.random(20, 25))
end,
do_punch = function (self, hitter)
minetest.log("action", "[In the Fog] Herobrine despawned because he was punched.")
if math.random(1, 100) <= herobrine_settings.get_setting("jumpscare_chance") then herobrine.jumpscare_player(hitter, nil, true) end
minetest.sound_fade(self.herobrine_ambience, 0.1, 0)
if herobrine_settings.random(1, 100, herobrine_settings.get_setting("jumpscare_chance")) then herobrine.jumpscare_player(hitter, nil, true) end
herobrine.despawnHerobrine(self)
return false
end,
@ -52,10 +71,10 @@ local def = {
self.despawn_timer = self.despawn_timer + dtime
if self.despawn_timer >= despawn_timer then
herobrine.despawnHerobrine(self)
minetest.sound_fade(self.herobrine_ambience, 0.1, 0)
minetest.log("action", "[In the Fog] Herobrine despawned due to the despawn timer.")
if math.random(1, 100) <= herobrine_settings.get_setting("convert_stalker") then
if herobrine_settings.random(1, 100, herobrine_settings.get_setting("convert_stalker")) then
minetest.after(0.25, function()
herobrine.spawnHerobrine("herobrine:herobrine", obj_pos)
end)
@ -67,41 +86,62 @@ local def = {
for _, obj in pairs(objects) do
if obj:is_player() then
herobrine.despawnHerobrine(self)
minetest.sound_fade(self.herobrine_ambience, 0.1, 0)
if math.random(1, 100) <= herobrine_settings.get_setting("jumpscare_chance") then herobrine.jumpscare_player(obj, nil, true) end
if herobrine_settings.random(1, 100, herobrine_settings.get_setting("jumpscare_chance")) then herobrine.jumpscare_player(obj, nil, true) end
minetest.log("action", string.format("[In the Fog] Herobrine despawned due to a player being within %d blocks of it.", despawn_radius))
return false
end
end
local day_count = herobrine.get_day_count()
self.texture_timer = self.texture_timer + dtime
if self.invisible and day_count > 6 then
self:do_attack()
else
self:stop_attack()
self.object:set_velocity({x = 0, y = 0, z = 0})
end
if self.texture_timer >= 4 and day_count > 6 then
local props = object:get_properties()
if not self.invisible then
props.textures = {"herobrine_footsteps.png"}
else
props.textures = {"herobrine.png"}
end
self.invisible = not self.invisible
object:set_properties(props)
self.texture_timer = 0
end
local pos = {}
if self.facing_pname == nil then
local players = minetest.get_connected_players()
pos = players[math.random(1, #players)]:get_pos()
pos = players[herobrine_settings.random(1, #players)]:get_pos()
else
local player = minetest.get_player_by_name(self.facing_pname)
pos = player:get_pos()
self:yaw_to_pos(pos, 0)
self:stop_attack()
if vector.distance(obj_pos, pos) > 120 then
minetest.log("action", "[In the Fog] Herobrine despawned because he was too far from the player.")
herobrine.despawnHerobrine(self)
return false
else
herobrine_awards.unlock(player:get_player_name(), "herobrine_awards:stalker")
end
pos.y = pos.y + 1
if not herobrine.line_of_sight(pos, obj_pos) then
return
return true
end
self.staring_timer = self.staring_timer + dtime
local dir = vector.direction(pos, obj_pos)
local pdir = player:get_look_dir()
local diff = vector.length(vector.subtract(dir, pdir))
if diff <= 0.325 and vector.distance(pos, obj_pos) <= 40 and self.despawn_timer >= 6 and self.staring_timer >= 3 then
if math.random(1, 10000) <= 1 then
self.object:set_pos(player:get_pos())
if herobrine_settings.random(1, 10000, 1) then
object:set_pos(player:get_pos())
end
if math.random(1, 10000) <= 1 then
if herobrine_settings.random(1, 10000, 1) then
herobrine.despawnHerobrine(self)
local id = player:hud_add({
@ -109,7 +149,7 @@ local def = {
alignment = {x = 0, y = 0},
position = {x = 0.5, y = 0.5},
scale = {x = 80, y = 80},
text = "[fill:80x80:#000000",
text = "herobrine_static.png^[opacity:245",
z_index = 1000,
})
minetest.after(3, function()

View File

@ -2,7 +2,11 @@ herobrine.register_on_day_change(function(daycount)
minetest.log("action", string.format("[In the Fog] NEW DAYCOUNT: %d.", daycount))
end)
herobrine.register_on_spawn(function(name, pos)
minetest.log("action", string.format("[In the Fog] %s spawned at %s.", name, minetest.pos_to_string(pos, 1)))
herobrine.register_on_spawn(function(luaentity)
minetest.log("action", string.format("[In the Fog] %s spawned at %s.", luaentity.name, minetest.pos_to_string(luaentity.object:get_pos(), 1)))
return true
end)
herobrine.register_on_despawn(function(luaentity)
minetest.log("action", "Herobrine has been despawned at " .. minetest.pos_to_string(luaentity.object:get_pos(), 1))
end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

View File

@ -21,20 +21,41 @@ function herobrine_ambience.get_ambience_list()
end
function herobrine_ambience.get_random_sound()
local sound_name = sounds[math.random(1, #sounds)]
local sound_name = sounds[herobrine_settings.random(1, #sounds)]
return sound_name, true
end
local ambience_volume = herobrine_settings.get_setting("ambience_volume") / 100
function herobrine_ambience.play_ambience(sound_name, duration)
local sound = minetest.sound_play({name = sound_name, gain = ambience_volume}, nil, false)
local job = minetest.after(duration, function()
if not sound then return end
minetest.sound_fade(sound, 0.1, 0)
local ids = {}
function herobrine_ambience.play_sound(spec, duration, parameters)
if type(spec) ~= "table" then
spec = {name = spec, gain = 1.0}
end
spec.gain = spec.gain or ambience_volume
if type(parameters) ~= "table" then
parameters = {}
end
local sound = minetest.sound_play(spec, parameters, false)
ids[sound] = true
local job = minetest.after(duration or 10, function()
herobrine_ambience.fade_sound(sound, 0.1, 0)
end)
return sound, job
end
function herobrine_ambience.fade_sound(handle, step, gain)
if not ids[handle] then
return false
end
minetest.sound_fade(handle, step, gain)
ids[handle] = nil
return true
end
for i = 1, 4 do
herobrine_ambience.register_sound("herobrine_ambience" .. tostring(i))
end
@ -46,9 +67,9 @@ minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer >= interval then
if math.random(1, 100) <= chance then
if herobrine_settings.random(1, 100, chance) then
local sound = herobrine_ambience.get_random_sound()
herobrine_ambience.play_ambience(sound, math.random(20, 25))
herobrine_ambience.play_sound(sound, herobrine_settings.random(20, 25))
end
timer = 0
end

View File

@ -6,7 +6,8 @@ local cmd = chatcmdbuilder.register("herobrine", {
description = "Command used for the In the Fog mod. Do /herobrine help to get started. Do /herobrine help true for the formspec version.",
privs = {
interact = true
}
},
params = "<help> [true]",
})
function herobrine_commands.register_subcommand(name, def, hidden)

View File

@ -1,3 +1,5 @@
local CURRENT_SETTING_VERSION = "2"
--> Save the settings on a world-to-world basis.
local types = {["table"] = true, ["boolean"] = true, ["string"] = true, ["number"] = true}
@ -80,6 +82,7 @@ function herobrine_settings.save_settings()
file:set(k, tostring(v))
end
end
file:set("setting_version", CURRENT_SETTING_VERSION)
local success = file:write()
return success
end
@ -87,6 +90,15 @@ end
function herobrine_settings.load_settings()
local settings = Settings(herobrine_settings.conf_modpath .. "/herobrine_settings.conf")
local settings_table = settings:to_table()
settings_table.setting_version = nil
if not settings:get("setting_version") then
return false
end
if not (tonumber(settings:get("setting_version")) >= tonumber(CURRENT_SETTING_VERSION)) then
return false
end
for k, v in pairs(settings_table) do
if k == nil then return end
--> Write in the logs what settings were modified in the config file. Good for debugging.
@ -121,4 +133,16 @@ function herobrine_settings.get_setting_val_from_day_count(name, days)
local tbl = def.value
return tbl.vals[herobrine_settings.nearest_value(tbl.days, days)], true
end
local rng = PcgRandom(21862175432869)
function herobrine_settings.random(min, max, num)
local rand = rng:next(min, max)
if not rand then
rand = math.random(min, max) --> Fallback just to be sure.
end
if not num then
return rand
end
return rand <= num
end

View File

@ -9,7 +9,7 @@ herobrine_settings.register_setting("spawnable_on", {
herobrine_settings.register_setting("despawn_timer", {
type = "number",
description = "How long it takes in seconds for Stalking Herobrine to despawn (in seconds).",
value = 20,
value = 25,
}, true)
herobrine_settings.register_setting("despawn_radius", {
@ -193,7 +193,22 @@ herobrine_settings.register_setting("torch_chance", {
type = "table",
description = "The chance for a random torch to break around the player.",
value = {
days = {6, 7, 10, 12},
vals = {0, 5, 10, 15},
days = {6, 7, 10, 12, 20},
vals = {0, 5, 7, 10, 5},
},
}, true)
}, true)
herobrine_settings.register_setting("herobrine_angry_meter", {
type = "table",
description = "Herobrine's anger meter.",
value = {
days = {11, 12, 14, 16, 20},
vals = {0, 2, 5, 10, 15},
},
}, true)
herobrine_settings.register_setting("herobrine_hunting_interval", {
type = "number",
description = "Interval between Regular Herobrine spawning.",
value = 420,
})

View File

@ -41,7 +41,7 @@ end)
local function settings_loop()
herobrine_settings.save_settings()
minetest.after(60, settings_loop)
minetest.after(30, settings_loop)
end
minetest.after(0, settings_loop)

View File

@ -9,7 +9,7 @@ local structure_modpath = minetest.get_modpath(minetest.get_current_modname()) .
minetest.register_decoration({
deco_type = "schematic",
place_on = {"group:stone"},
sidelen = 9,
sidelen = 16,
fill_ratio = 0.00003,
y_max = -30000,
y_min = -50,
@ -22,7 +22,7 @@ minetest.register_decoration({
minetest.register_decoration({
deco_type = "schematic",
place_on = {"group:sand", "group:water"},
sidelen = 9,
sidelen = 16,
fill_ratio = 0.00003,
y_max = 30000,
y_min = 2,