Compare commits

..

No commits in common. "96d2be9ebd39ef8e1313f164b6ddad964773acc6" and "282128382d22f861b2ef021e40b883006843c53d" have entirely different histories.

7 changed files with 100 additions and 156 deletions

View file

@ -91,14 +91,11 @@ end
local function set_max_hp(player, max_hp)
local cur_hp = player:get_hp()
local old_max = player:get_properties().hp_max
if old_max == 0 then
minetest.log("error", "[ctf_classes] Reviving dead player " .. player:get_player_name())
end
player:set_properties({hp_max = max_hp})
local new_hp = cur_hp + max_hp - old_max
player:set_properties({
hp_max = max_hp
})
if new_hp > max_hp then
minetest.log("error", string.format("New hp %d is larger than new max %d, old max is %d", new_hp, max_hp, old_max))
new_hp = max_hp

View file

@ -10,10 +10,8 @@ local items = {
"* Use medkits to replenish health gradually.",
"* Gain more score by killing more than you die, or by capturing the flag.",
"* Players are immune for 5 seconds after they respawn.",
"* Access the pro section of the chest by achieving 10k+ score and either",
" killing 3 people for every 2 deaths and capturing the flag at least 10 times",
" or killing as many people as you die, capturing the flag on every 3rd attempt",
" and at least 30 times.",
"* Access the pro section of the chest by achieving 2k+ score,",
" killing 3 people for every 2 deaths, and capturing the flag at least 10 times",
"",
color .. "Team Co-op",
@ -32,12 +30,12 @@ local items = {
color .. "Contact Moderators",
"",
"* Report people using /report.",
"* Report people using /report or the #reports channel in Discord",
"",
color .. "Other",
"",
"* Capture The Flag Discord (not related to this server): https://discord.gg/vcZTRPX",
"* Capture The Flag Discord: https://discord.gg/vcZTRPX",
}
for i = 1, #items do
items[i] = minetest.formspec_escape(items[i])

View file

@ -1,84 +1,88 @@
# CTF map-maker mod
# CTF Map - Map maker
## Making a new map
## Creating a new map
### Youtube Tutorial
### Youtube tutorial
https://youtu.be/orBsC9wViUw
### Dependencies
- Minetest 5.0.0 or later (https://minetest.net/)
- Minetest Game (https://github.com/minetest/minetest_game/) (CTF supports most MTG nodes)
- `ctf_map` modpack (copy this folder to `minetest/mods`)
- `worldedit` modpack (WE) (https://content.minetest.net/packages/sfan5/worldedit/)
### Find an area
### 1. Dependencies
- The area can be maximum 230x230 blocks in surface area, but it can be lesser.
- Modify the area to *your* unique ctf_map
- you could add
- buildings
- lakes
- hills
- etc.
- If you haven't modified the map at all, do the following to speed up barrier placement:
* Minetest 5.0.0 or later.
* `ctf_map` modpack (by copying the folder from this game to `minetest/mods`)
* `worldedit` and `worldedit_commands`.
- Stop Minetest.
- Open up the world's world.mt
- Set backend to "dummy".
- Save.
### 2. Find an area
### The `gui`window
* Can use Minetest Game and any mapgen.
* It must be a cube, and the barrier will be in the exact center.
* It should be around 230x230 in surface area, but this can be lesser.
* Feel free to modify the area to your needs.
![gui-window](./gui.png)
### 3. Select the area
There are many ways of placing the barrier:
There are multiple ways do this, this is the simplest in most cases.
- Go to the center of the map and click on `Player Pos` and then on `To WE`
- set a radius and a height for the map
- **Or** select the area of the map via WE
- Go to one corner of the map and type `//pos 1` in the chat
- Then go to the opposite corner of the cube and type `//pos 2` in the chat
- Click on `From WE` to import the positions
- **If `h` is negative change it to the positive number** (`-130 -> 130`)
- **Both radii must be the same!**
- The rotation of the map has to be `z=0` (currently x=0 creates bugs and errors)
- Click on `Place Barriers` (Note that this has no undo)
- After the barriers are placed, click on `Givme Flags` to get 2 flags and place them at the bases.
* If you haven't modified the map at all, do the following to speed up barrier placement:
* Stop Minetest.
* Open up the world's world.mt
* Set backend to "dummy".
* Save.
* Using worldedit, select the area.
* Type `/gui`, and click `Player pos` then `From WE` and then `To WE`.
* Check that the center location is the right place for the barrier to go.
* Check that the bounds extend far enough.
### Meta Data
### 4. Place barriers
The `gui`window only shows the most important things. You have to add the missing in the `map.conf` later.
* The barrier is a plane defined by co-ordinate (=0).
* If you choose `X=0` the barrier will be placed having the X co-ordinate as 0. But from a few months, the `X=0` co-ordinate creates bugs and errors. It's better if you choose `Z=0` for creating your map.
* If you choose `Z=0` The barrier will be placed having the Z co-ordinate as 0.
* Click "place barrier". Note that this command does not have an undo.
* After placing barriers you should place 2 flags where you want bases to be. You get flags in `/gui` --> `Giveme flags`
### Exporting
### 5. Meta data
- Click on `Export` to export the map-files. This may takes some time
* Set the meta data
## Map Meta
### 6. Export
The metadata of each map are stored in the `map.conf` file and includes all important information about them:
- `name`: Name of the map.
- `author`: Author of the map.
- `hint` [Optional]: A helpful tip for players to understand unique maps.
- `roation`: The rotation of the map. [x|y]
- `r`: Radius of the map.
- `h`: Heigt of the map (**If it's an odd numer, make h=h+1 `107->108`**).
- `team.i`: Name of the team.
- `team.i.color`: Color of the team.
- `team.i.pos`: Position of team `i`'s flag, relative ot the center of schem. **The y-positions of the flags must be an integer!** `30,-32.5,60 -> 30,-33,60`
- `chest.i.from` and `chests.i.to` [Optional]: Positions of diagonal corners of custom chest zone `i`, relative to the center of the schem.
- `chests.i.n` [Optional]: Number if chests in zone `i`
- `license`: Name of license of the map.
- `other` [Optional]: Additional information about the map. This is displayed in the maps catalog.
- `base_node` [Optional]: String of the node around the flags.
- `initial_stuff` [Optional]: Comma-separated list of itemstacks to be given to the player on join and on respawn.
- `treasures` [Optional]: List of treasures to be registered for the map, in a serialized format. Refer to the `treasures` sub-section for more details.
- `start_time` [Optional]: Time of day when the match starts. Default to `0.4` [`0 - 1`].
- `time_speed` [Optional]: Time speed multiplier. Accepts any valid number. Defaults to 1.
- `phys_speed` [Optional]: Player speed multiplier. Accepts any valid number. Defaults to 1.
- `phys_jump` [Optional]: Player jump multiplier. Accepts any valid number. Defaults to 1.
- `phys_gravity` [Optional]: Player gravity multiplier. Accepts any valid number. Defaults to 1.
* Click export, and wait until completion.
* Copy the resultant folder from `worlddir/schems/` into `games/capturetheflag/mods/ctf/ctf_map/ctf_map_core/maps/`.
* Profit!
## Documentation
### Map meta
Each map's metadata is stored in an accompanying `map.conf` file containing the following data:
* `name`: Name of map.
* `author`: Author of the map.
* `hint`: [Optional] Helpful hint or tip for unique maps, to help players understand the map.
* `rotation`: Rotation of the schem. [`x`|`z`]
* `r`: Radius of the map.
* `h`: Height of the map.
* `team.i`: Name of team `i`.
* `team.i.color`: Color of team `i`.
* `team.i.pos`: Position of team `i`'s flag, relative to center of schem.
* `chests.i.from`, `chests.i.to`: [Optional] Positions of diagonal corners of custom chest
zone `i`, relative to the center of the schem.
* `chests.i.n`: [Optional] Number of chests to place in custom chest zone `i`.
* `license`: Name of the license of the map.
* `other`: [Optional] Misc. information about the map. This is displayed in the maps catalog.
* `base_node`: [Optional] Technical name of node to be used for the team base.
* `initial_stuff`: [Optional] Comma-separated list of itemstacks to be given to the player
on join and on respawn.
* `treasures`: [Optional] List of treasures to be registered for the map, in a serialized
format. Refer to the `treasures` sub-section for more details.
* `start_time`: [Optional] Time at start of match. Defaults to `0.4` [`0` - `1`].
* `time_speed`: [Optional] Time speed multiplier. Accepts any valid number. Defaults to 1.
* `phys_speed`: [Optional] Player speed multiplier. Accepts any valid number. Defaults to 1.
* `phys_jump`: [Optional] Player jump multiplier. Accepts any valid number. Defaults to 1.
* `phys_gravity`: [Optional] Player gravity multiplier. Accepts any valid number. Defaults to 1.
#### `license`
* Every map must have its own license. Once you've chosen your license, simply add the following line to the `map.conf` file:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

View file

@ -37,18 +37,13 @@ minetest.register_on_mods_loaded(function()
table.insert(minetest.registered_on_respawnplayers, 1, function(player)
local pname = player:get_player_name()
if ctf_respawn_delay.players[pname] then
-- Since the player is still dead the client can send respawn actions
-- https://github.com/minetest/minetest/blob/4152227f17315a9cf9038266d9f9bb06e21e3424/src/network/serverpackethandler.cpp#L895
-- We should ignore those
if ctf_respawn_delay.players[pname].timeleft == "waiting" then
ctf_respawn_delay.players[pname].timeleft = RESPAWN_DELAY
local pos = player:get_pos()
pos.y = ctf_map.map.h/2 + 10
if ctf_respawn_delay.players[pname] and ctf_respawn_delay.players[pname].timeleft == "waiting" then
ctf_respawn_delay.players[pname].timeleft = RESPAWN_DELAY
local pos = player:get_pos()
pos.y = ctf_map.map.h/2 + 10
player:set_pos(pos) -- Player will be stuck there because CTF 'air' is walkable
minetest.after(RESPAWN_INTERVAL, respawnfunc, pname)
end
player:set_pos(pos) -- Player will be stuck there because CTF 'air' is walkable
minetest.after(RESPAWN_INTERVAL, respawnfunc, pname)
return true
end
@ -61,10 +56,15 @@ minetest.register_on_mods_loaded(function()
end)
end)
function respawnplayer(player, pname)
player:hud_remove(ctf_respawn_delay.players[pname].hudid)
player:set_properties({hp_max = ctf_respawn_delay.players[pname].old_max})
player:set_hp(ctf_respawn_delay.players[pname].old_max)
function ctf_respawn_delay.respawnplayer(name)
local player = minetest.get_player_by_name(name)
if not player then return end
player:hud_remove(ctf_respawn_delay.players[name].hudid)
player:set_properties({hp_max = ctf_respawn_delay.players[name].old_max})
player:set_hp(ctf_respawn_delay.players[name].old_max)
ctf_respawn_delay.players[name] = nil
for k, func in ipairs(ctf_respawn_delay.registered_on_respawnplayers) do
func(player)
@ -72,13 +72,16 @@ function respawnplayer(player, pname)
end
function respawnfunc(pname)
if not ctf_respawn_delay.players[pname] then
local player = minetest.get_player_by_name(pname)
if not player or not ctf_respawn_delay.players[pname] then
ctf_respawn_delay.players[pname] = nil
return
end
local player = minetest.get_player_by_name(pname)
if not player then
ctf_respawn_delay.players[pname] = nil
if type(ctf_respawn_delay.players[pname].timeleft) == "string" then
minetest.after(RESPAWN_INTERVAL, respawnfunc, pname)
return
end
@ -90,26 +93,12 @@ function respawnfunc(pname)
minetest.after(RESPAWN_INTERVAL, respawnfunc, pname)
else
respawnplayer(player, pname)
ctf_respawn_delay.players[pname] = nil
ctf_respawn_delay.respawnplayer(pname)
end
end
ctf_match.register_on_new_match(function()
for pname in pairs(ctf_respawn_delay.players) do
local player = minetest.get_player_by_name(pname)
if player then
respawnplayer(player, pname)
end
end
ctf_respawn_delay.players = {}
end)
minetest.register_on_leaveplayer(function(player)
local pname = player:get_player_name()
if ctf_respawn_delay.players[pname] then
player:set_properties({hp_max = ctf_respawn_delay.players[pname].old_max})
ctf_respawn_delay.players[pname] = nil
for name in pairs(ctf_respawn_delay.players) do
ctf_respawn_delay.respawnplayer(name)
end
end)

View file

@ -259,48 +259,3 @@ minetest.register_chatcommand("makepro", {
end
end
})
minetest.register_chatcommand("makecapturepro", {
params = "[player_name]",
description = "Make player a 'capture pro'",
privs = {ctf_admin = true},
func = function(name, param)
-- Check if param is specified, else target the caller
param = param:trim()
if param == "" then
param = name
end
local modified = false
local stats = ctf_stats.player(param)
local deaths = math.max(stats.deaths, 1)
if stats.kills < 1.0 * deaths then
stats.kills = math.ceil(1.01 * deaths)
modified = true
end
if stats.score < 10000 then
stats.score = 10000
modified = true
end
if stats.captures < 30 then
stats.captures = 30
modified = true
end
local attempts = math.max(stats.attempts, 1)
if stats.captures < 0.33 * attempts then
stats.captures = math.ceil(0.34 * attempts)
modified = true
end
if modified then
ctf_stats.request_save()
return true, "Made " .. param .. " a pro!"
else
return false, param .. " is already a pro!"
end
end
})

View file

@ -578,6 +578,7 @@ minetest.register_node("default:clay", {
description = "Clay",
tiles = {"default_clay.png"},
groups = {crumbly = 3},
drop = 'default:clay_lump 4',
sounds = default.node_sound_dirt_defaults(),
})