123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122 |
- if not minetest.global_exists("survivalist") then survivalist = {} end
- survivalist.modpath = minetest.get_modpath("survivalist")
- survivalist.players = survivalist.players or {}
- survivalist.groups = survivalist.groups or {}
- survivalist.xp_minimum = 700
- survivalist.xp_surface = 700
- survivalist.xp_cave = 1500
- survivalist.xp_nether = 2400
- survivalist.completion_xp_surface = 1100
- survivalist.completion_xp_cave = 2700
- survivalist.completion_xp_nether = 4500
- function survivalist.have_xp(pname, ch)
- local amount = (survivalist["xp_" .. ch]) or 0
- return (xp.get_xp(pname, "digxp") >= amount)
- end
- local vector_distance = vector.distance
- local vector_round = vector.round
- local math_floor = math.floor
- local math_random = math.random
- local surfacecitypos = {x=0, y=-8, z=0}
- local nethercitypos = {x=0, y=-30793, z=0}
- survivalist.gamerules =
- "===| Survival Challenge Description |===\n\n" ..
- "This page contains the rules for this mini-game, with options to begin a Challenge or claim victory on a Challenge currently in-progress.\n\n" ..
- "The Survival Challenge focuses on survival in the wild far from developed regions. You can play it solo or with other players.\n\n" ..
- "You will need to scroll this text in order to read all of it.\n\n" ..
- "When beginning a Challenge it is possible to end up in a starting situation where survival is impossible. You always have the option to cancel without affecting your score.\n\n" ..
- "On accepting a challenge you are transported into a small dungeon, which is at a distant location in the world very far from the Surface Colony and the Nether City. The minimum distance you’ll be teleported is 10,000 meters; the server will not choose a dungeon closer to either city than this. You’ll have the basic starting items that every player starts with when they first join the server, and the dungeon has a chest containing additional items to make getting a head-start a little easier, since otherwise some scenarios would be impossible to beat. The chest contents differ between challenge types and are somewhat random.\n\n" ..
- "Before you can begin a challenge all your inventories must be empty: your main inventory, your craft grid, the craft-preview and craft-output inventory slots (yes, those too, cheaters!), your Star-Fissure Box, your armor inventory, your bags, and the wielditem inventory (if you don’t know what this is, then don’t worry about it). Proof of Citizenship tokens are exempt.\n\n" ..
- "You can play this mini-game cooperatively. To do so one player should to start a Survival Challenge just as if they were going to play solo. Whenever a player starts a Challenge there is a 5 minute window in which other players can join the first player by being transported to the same dungeon. To join another player in their dungeon, you must stand within 5 meters of the place where they stood at the time they began their Challenge. You must also choose the same gamemode (Iceworld, Underearth, or Netherealm) as the first player. If you are too far away, or you choose a wrong gamemode, or the 5 minute window has passed, you won’t be transported to the same dungeon. If you are are unsuccessful and are not teleported to the same dungeon, you can simply cancel and try again if you wish. There is no limit on the number of players who may play cooperatively. Every player who joins extends the 5-minute window a bit. Do note that supplies are not increased with each player beyond the first, so you’ll need to share. Players win or lose the Challenge separately, so if one player has a fatal accident, the remaining players can keep playing.\n\n" ..
- "Finding a suitable location to build the starting dungeon can take the server some time, so you have a few seconds to interact with the world after accepting a challenge. Don’t rely on this, though.\n\n" ..
- "(Note to builders in distant lands: the server will not overwrite any of your builds when creating a player’s starting dungeon, as long as your builds are protected. Although the world is vast and the chance of randomly selecting a location inside someone else’s home is small, the server nonetheless performs checks to avoid accidents.)\n\n" ..
- "In order to win after starting a challenge, you must find your way back to the Surface Colony OR the Nether City and claim victory (press the ‘Claim Victory’ button below these rules) in the Central Square of either location. Finding civilization to claim victory is your goal; avoiding a fatal death during your travels in the wild is your challenge. Rules for death are below the Challenge descriptions.\n\n" ..
- "Note that you may to use your Proof of Citizenship to teleport you the rest of the way to the Surface Colony or Nether City once you are in range of the teleport beacons. Use of diamond teleporters is also allowed, as are flameportals which go to and from the Netherealm, or any other form of transportation. However, when starting a challenge your flameportal’s previous return position (if you had one set) is erased to prevent using a return portal as a ‘cheat’ to obtain an easy win. The same is true for beds.\n\n" ..
- "There are three challenge types: the Iceworld Challenge, the Underearth Challenge, and the Netherealm Challenge, with difficulty being in that order. Each challenge awards Skill Marks when victory is successfully claimed. The Skill Marks are Copper, Silver, and Gold. The amount of marks you’ll receive on successful completion of a challenge depends on the distance you travel to either the Surface Colony or the Nether City, starting from your initial dungeon. You receive 1 mark for every 1K meters of distance (rounded down), minus the first 10 kilometers. You always receive at least 1 Skill Mark.\n\n" ..
- "The following is a basic description of each challenge.\n\n" ..
- "In the Iceworld Challenge you start in an ice-and-brick dungeon at what is normally sea-level (if this server were to have a liquid sea). Chances are, you’ll be under a mountain or below a raised plain, so your first goal will be to dig up and find the surface. If you are very lucky you will be on an ice-lake instead. Avoid the icemen and don’t go out at night! This is the easiest challenge. The first time you complete it successfully, the skill learned causes your wield-hotbar (the 8 itemslots below your health and hunger stats) to expand to 16 slots for easier building. (Note: if you prefer the regular 8 slots anyway and don’t want the bigger version, you can let the server administrator know, to get it reset back to 8 slots!)\n\n" ..
- "In the Underearth Challenge you start in a cobble dungeon deep under the earth, between -24K and -3K. Since you are underground, your first priority is using the materials in the starting chest to build a small farm. Note that the server never locates a dungeon to be floating in the middle of a caverealm void, but it is remotely possible that you could have lava outside the dungeon walls. Once you have a food source, the main difficulty is digging your way to the surface or to the nether (if you choose to claim victory in the Nether City). Beware of mining instabilities! Note that this Challenge typically takes the longest to complete. Once you’ve established a base with a bed, consider using Obsidian Gateways to try and bring yourself closer to the surface. The first time you complete this Challenge, you unlock a hidden feature of the Key of Citizenship which allows you to jaunt (teleport) to other players who also possess a Key—provided their Key’s beacon signal can be successfully triangulated ….\n\n" ..
- "The Netherealm Challenge is similar to the Underearth Challenge, except that your starting dungeon is located in the second-worst place in the world, some 60 meters under the brimstone ocean. (The worst place in the world is the islands directly above all that lava.) Your starting dungeon is made of black rackstone, but don’t imagine you’ll be able to use it for anything except stone picks. You need to be very, very careful in this challenge, because lava is everywhere, and netherack is nasty to dig. There are very few usable resources in the nether, so finding the few resources you can is very important. The first thing you need to do is dig up to the islands without letting the brimstone ocean flow into your dungeon. Once there you can explore the brimstone cavern for a few meager resources. In this Challenge, you are recommended to claim victory in the Nether City rather than attempt to dig to the surface. However, those who dig to the surface will receive more reward. If you choose to dig up out of the nether into normal rock you’ll be able to find a few more resources, and the caverealms of the Underearth Challenge will seem like a garden. :-) The first time you beat this Challenge, you unlock a hidden feature of the Key of Citizenship which allows you to access its little-understood cloaking capabilities, which can render you invisible in all but a few circumstances ….\n\n" ..
- "After starting a Challenge you may cancel it without affecting your death/success score. This option is available as long as a Challenge is running. The conditions for canceling a challenge are the same as the conditions for starting one: all your inventories must be empty except for passport tokens. (You cannot bring anything with you when you cancel.) You may choose this option if, for instance, you do not like your starting situation. When you cancel a Challenge you are returned to the same spot you were when you began the Challenge.\n\n" ..
- "Rules for death: you lose the Challenge if you die and have not slept in a bed. Lacking a bed is your initial state whenever you begin a Challenge, and you avoid losing the Challenge by crafting a bed and sleeping in it. Afterwards if you die you will respawn in your bed and the Challenge will continue as before. Note that a bed is only good for a limited number of respawns, so you should remember to sleep often to refresh it.\n\n" ..
- "Warning: since your bed is lost if you are killed by another player (but not by a mob or the environment), the effect of being murdered is that you will fail the Challenge. Your murderer does not get any special benefits other than hearing your screams of fury.\n\n" ..
- "Each player’s total number of victories, fatal deaths, and victory streaks are recorded permanently, as well as the number of victories in the three individual challenges, and the total number of marks earned. This information is never reset.\n\n" ..
- "===| Challenge Description End |==="
- function survivalist.add_player_to_rankings(pname)
-
- local data = survivalist.modstorage:get_string(":ranked_players:")
-
- if data == "" then
- data = "return {}"
- end
-
- local tb = minetest.deserialize(data)
-
- tb[pname] = true
-
- local serialized = minetest.serialize(tb)
-
- if type(serialized) == "string" then
- survivalist.modstorage:set_string(":ranked_players:", serialized)
- end
- end
- function survivalist.get_ranking_entries()
-
- local data = survivalist.modstorage:get_string(":ranked_players:")
-
- if data == "" then
- data = "return {}"
- end
-
- local tb = minetest.deserialize(data)
-
- return tb or {}
- end
- function survivalist.inventory_empty(inv, name)
- local count = 0
- for i = 1, inv:get_size(name) do
- local stack = inv:get_stack(name, i)
- if not passport.is_passport(stack:get_name()) then
- if stack:get_count() > 0 then
- count = count + stack:get_count()
- end
- end
- end
- return (count == 0)
- end
- function survivalist.check_inventories_empty(pname)
- local player = minetest.get_player_by_name(pname)
- if not player then
- return
- end
- local inv = player:get_inventory()
- if survivalist.inventory_empty(inv, "main") and
- survivalist.inventory_empty(inv, "craft") and
- survivalist.inventory_empty(inv, "armor") and
- survivalist.inventory_empty(inv, "voidchest:voidchest") and
- survivalist.inventory_empty(inv, "craftresult") and
- survivalist.inventory_empty(inv, "craftpreview") and
- survivalist.inventory_empty(inv, "bag1contents") and
- survivalist.inventory_empty(inv, "bag2contents") and
- survivalist.inventory_empty(inv, "bag3contents") and
- survivalist.inventory_empty(inv, "bag4contents") and
- survivalist.inventory_empty(inv, "xchest") and
- survivalist.inventory_empty(inv, "bag1") and
- survivalist.inventory_empty(inv, "bag2") and
- survivalist.inventory_empty(inv, "bag3") and
- survivalist.inventory_empty(inv, "bag4") then
- return true
- end
- end
- dofile(survivalist.modpath .. "/loot.lua")
- function survivalist.teleport_and_announce(pname, pos, gamemode)
- local player = minetest.get_player_by_name(pname)
- if not player then
- return
- end
-
-
- if not survivalist.check_inventories_empty(pname) then
- minetest.chat_send_player(pname, "# Server: All your inventories (including the Starfissure Box and armor) must be empty before you can begin a challenge (the Proof of Citizenship does not count). You will receive starting items when you begin.")
- easyvend.sound_error(pname)
- return
- end
-
- if default.player_attached[pname] then
- minetest.chat_send_player(pname, "# Server: Transport error. Player attached!")
- return
- end
-
- local homepos = vector_round(player:get_pos())
-
- wield3d.on_teleport()
- player:set_pos(vector.add(pos, {x=math_random(-3, 3), y=0.5, z=math_random(-3, 3)}))
-
-
- heal.heal_health_and_hunger(pname)
-
-
- flameportal.clear_return_location(pname)
-
- local old_bed_pos = beds.get_respawn_pos_or_nil(pname)
- if old_bed_pos then
- local pmeta = player:get_meta()
- pmeta:set_string("survivalist_old_bed_pos", minetest.pos_to_string(old_bed_pos))
- end
- beds.clear_player_spawn(pname)
-
-
- local gamestring = "Void"
- if gamemode == "surface" then
- gamestring = "Iceworld"
- elseif gamemode == "cave" then
- gamestring = "Underearth"
- elseif gamemode == "nether" then
- gamestring = "Netherealm"
- end
-
-
- if not gdac.player_is_admin(pname) then
- local dname = rename.gpn(pname)
- minetest.chat_send_all("# Server: Player <" .. dname .. "> has begun a test of skill in the " .. gamestring .. " at " .. rc.pos_to_namestr(vector_round(pos)) .. "!")
- else
- minetest.chat_send_player(pname, "# Server: You have begun a test of skill in the " .. gamestring .. " at " .. rc.pos_to_namestr(vector_round(pos)) .. "!")
- end
- survivalist.shout_player_stats(pname)
- minetest.chat_send_player(pname, "# Server: To win, you must find the city and claim victory in the Main Square. If you die without sleeping, you will fail the Challenge.")
- beds.report_respawn_status(pname)
-
-
- give_initial_stuff.give(player)
-
-
- survivalist.modstorage:set_string(pname .. ":mode", gamemode)
-
-
- survivalist.modstorage:set_string(pname .. ":pos", minetest.pos_to_string(vector_round(pos)))
-
- survivalist.modstorage:set_string(pname .. ":home", minetest.pos_to_string(homepos))
-
- survivalist.modstorage:set_string(pname .. ":xp", tostring(xp.get_xp(pname, "digxp")))
-
- survivalist.groups[pname] = survivalist.groups[pname] or {count=0}
- survivalist.groups[pname].count = survivalist.groups[pname].count + 1
- minetest.after(60*5, function()
- if survivalist.groups[pname] then
- survivalist.groups[pname].count = survivalist.groups[pname].count - 1
- if survivalist.groups[pname].count <= 0 then
- survivalist.groups[pname] = nil
- end
- end
- end)
- end
- function survivalist.prepare_dungeon(pname, pos, gamemode)
-
- local minp = vector.add(pos, vector.new(-64, -64, -64))
- local maxp = vector.add(pos, vector.new(64, 64, 64))
-
-
- local dminp = vector.add(pos, vector.new(-4, 0, -4))
- local dmaxp = vector.add(pos, vector.new(4, 4, 4))
-
-
- local pos2 = table.copy(pos)
-
-
- local tbparam = {}
- local cb = function(blockpos, action, calls_remaining, param)
- if action == core.EMERGE_CANCELLED or action == core.EMERGE_ERRORED then
- minetest.chat_send_player(pname, "# Server: Internal error, try again or report.")
- easyvend.sound_error(pname)
- return
- end
-
- if calls_remaining ~= 0 then
- return
- end
-
- if city_block:in_city_suburbs(pos2) then
- minetest.chat_send_player(pname, "# Server: Error: did not succeed in finding a suitable start location! If this happens, just try again.")
- easyvend.sound_error(pname)
- return
- end
-
-
- for x = dminp.x, dmaxp.x, 1 do
- for y = dminp.y, dmaxp.y, 1 do
- for z = dminp.z, dmaxp.z, 1 do
- if minetest.test_protection({x=x, y=y, z=z}, "") then
-
- minetest.chat_send_player(pname, "# Server: Error: did not succeed in finding a suitable start location! If this happens, just try again.")
- easyvend.sound_error(pname)
- return
- end
- end
- end
- end
-
-
- if minetest.get_node(pos2).name == "air" then
- minetest.chat_send_player(pname, "# Server: Error: did not succeed in finding a suitable start location! If this happens, just try again.")
- easyvend.sound_error(pname)
- return
- end
-
-
- local path = survivalist.modpath .. "/schematics/survivalist_" .. gamemode .. "_dungeon.mts"
- minetest.place_schematic(vector.add(pos2, {x=-4, y=0, z=-4}), path, "random", nil, true)
-
-
- local chestpos = vector.add(pos2, vector.new(math_random(-3, 3), 1, math_random(-3, 3)))
- chestpos = vector_round(chestpos)
-
-
- minetest.set_node(chestpos, {
- name = "morechests:goldchest_public_closed",
- param2 = math_random(0, 3),
- })
- local meta = minetest.get_meta(chestpos)
- local inv = meta:get_inventory()
- if inv then
- survivalist.fill_loot_chest(inv, gamemode)
- end
-
-
- survivalist.teleport_and_announce(pname, pos2, gamemode)
- end
-
-
- minetest.chat_send_player(pname, "# Server: Checking reliability of target location ... please stand by, this can take several seconds.")
- minetest.emerge_area(minp, maxp, cb, tbparam)
- end
- function survivalist.shout_player_stats(pname)
- local ms = survivalist.modstorage
- local wins_total = pname .. ":wins_total"
- local wins_streak = pname .. ":wins_streak"
- local wins_surface = pname .. ":wins_surface"
- local wins_cave = pname .. ":wins_cave"
- local wins_nether = pname .. ":wins_nether"
- local wins_fail = pname .. ":wins_fail"
- local wins_bstreak = pname .. ":wins_bstreak"
- local wins_tokens = pname .. ":wins_tokens"
-
- if not gdac.player_is_admin(pname) then
- local dname = rename.gpn(pname)
- minetest.chat_send_all("# Server: Survivalist stats for <" ..
- dname .. ">: Victories: " .. ms:get_int(wins_total) ..
- ". Deaths: " .. ms:get_int(wins_fail) ..
- ". Iceworld: " .. ms:get_int(wins_surface) ..
- ". Underearth: " .. ms:get_int(wins_cave) ..
- ". Netherealm: " .. ms:get_int(wins_nether) ..
- ". C-Streak: " .. ms:get_int(wins_streak) ..
- ". B-Streak: " .. ms:get_int(wins_bstreak) ..
- ". Marks: " .. ms:get_int(wins_tokens) ..
- ".")
- end
- end
- function survivalist.game_in_progress(pname)
- local cg = survivalist.modstorage:get_string(pname .. ":mode")
- if cg == "surface" or cg == "cave" or cg == "nether" then
- return true
- end
- end
- function survivalist.start_game(pname, gamemode)
-
- local player = minetest.get_player_by_name(pname)
- if not player then
- return
- end
-
-
- local currentgame = survivalist.modstorage:get_string(pname .. ":mode")
- if currentgame == "surface" or currentgame == "cave" or currentgame == "nether" then
- minetest.chat_send_player(pname, "# Server: You are already engaged in a Survivalist Challenge, you cannot start a concurrent game.")
- easyvend.sound_error(pname)
- return
- end
- local pp = player:get_pos()
- if pp.y < -100 or pp.y > 1000 then
- minetest.chat_send_player(pname, "# Server: You need to be on the surface of the Overworld to start a challenge.")
- easyvend.sound_error(pname)
- return
- end
-
- if type(gamemode) ~= "string" then
- minetest.chat_send_player(pname, "# Server: No starting option selected!")
- easyvend.sound_error(pname)
- return
- end
- if gamemode ~= "surface" and gamemode ~= "cave" and gamemode ~= "nether" then
- minetest.chat_send_player(pname, "# Server: You must choose a valid starting option!")
- easyvend.sound_error(pname)
- return
- end
-
- if not survivalist.have_xp(pname, gamemode) then
- minetest.chat_send_player(pname, "# Server: Insufficient XP to start this Challenge.")
- easyvend.sound_error(pname)
- return
- end
-
-
- if not survivalist.check_inventories_empty(pname) then
- minetest.chat_send_player(pname, "# Server: All your inventories (including the Starfissure Box and armor) must be empty before you can begin a challenge (the Proof of Citizenship does not count). You will receive starting items when you begin.")
- easyvend.sound_error(pname)
- return
- end
- local pos = {x=0, y=0, z=0}
- local group = false
-
- local players = minetest.get_connected_players()
- for k, v in ipairs(players) do
- local oname = v:get_player_name()
- local omode = survivalist.modstorage:get_string(oname .. ":mode")
-
- if omode == gamemode then
- local opos = minetest.string_to_pos(survivalist.modstorage:get_string(oname .. ":home"))
-
- if opos then
-
- if vector_distance(opos, player:get_pos()) <= 5 then
-
-
-
-
- if survivalist.groups[oname] then
-
- local p2 = minetest.string_to_pos(survivalist.modstorage:get_string(oname .. ":pos"))
- if p2 then
- pos = p2
- group = true
- break
- end
- end
- end
- end
- end
- end
- if not group then
-
- while vector_distance(pos, surfacecitypos) < 10000 or vector_distance(pos, nethercitypos) < 10000 do
- for j, k in ipairs({"x", "z"}) do
- pos[k] = math_random(-30000, 30000)
- end
-
- if gamemode == "surface" then
- pos.y = -10
- elseif gamemode == "cave" then
- pos.y = math_random(-24000, -3000)
- elseif gamemode == "nether" then
- pos.y = math_random(-30860, -30810)
- end
- end
- end
-
- if group then
-
- survivalist.teleport_and_announce(pname, pos, gamemode)
- else
-
- survivalist.prepare_dungeon(pname, pos, gamemode)
- end
- end
- function survivalist.player_in_victory_range(pname)
- local player = minetest.get_player_by_name(pname)
- if not player then
- return
- end
- local pos = player:get_pos()
- if vector_distance(pos, surfacecitypos) <= 20 then
- return true
- elseif vector_distance(pos, nethercitypos) <= 20 then
- return true
- end
- end
- function survivalist.attempt_claim(pname)
- local player = minetest.get_player_by_name(pname)
- if not player then
- return
- end
-
-
- local currentgame = survivalist.modstorage:get_string(pname .. ":mode")
- if currentgame ~= "surface" and currentgame ~= "cave" and currentgame ~= "nether" then
- minetest.chat_send_player(pname, "# Server: You are not currently engaged in a Survivalist Challenge.")
- easyvend.sound_error(pname)
- return
- end
-
-
-
- do
- local sxp = survivalist.modstorage:get_string(pname .. ":xp")
- local oxp = math.floor(tonumber(sxp) or 0)
- local cxp = math.floor(xp.get_xp(pname, "digxp"))
- local wxp = (survivalist["completion_xp_" .. currentgame]) or 0
- local dxp = (cxp - oxp)
- if dxp < wxp then
- local nxp = math.floor(oxp + wxp)
- minetest.chat_send_player(pname, "# Server: You need to obtain at least " .. wxp .. " XP over the course of the Challenge, first.")
- minetest.chat_send_player(pname, "# Server: You started with " .. oxp .. " XP. You must reach " .. nxp .. " XP!")
- easyvend.sound_error(pname)
- return
- end
- end
-
-
- local pos = player:get_pos()
- local cityname = ""
- local home_pos = minetest.string_to_pos(survivalist.modstorage:get_string(pname .. ":home"))
-
- local finalcitypos
- if vector_distance(pos, surfacecitypos) <= 20 then
- finalcitypos = table.copy(surfacecitypos)
- cityname = "Surface Colony"
- elseif vector_distance(pos, nethercitypos) <= 20 then
- finalcitypos = table.copy(nethercitypos)
- cityname = "Nether City"
- elseif vector_distance(pos, home_pos) <= 20 then
- finalcitypos = table.copy(home_pos)
- cityname = "place they started"
- end
-
- if not finalcitypos then
- minetest.chat_send_player(pname, "# Server: You must be within 20 meters of the main square of the Surface Colony or the Nether City or the place where you started the challenge in order to claim victory!")
- easyvend.sound_error(pname)
- return
- end
-
-
- local ranks = {
- ["surface"] = {rank="copper", upper="Copper"},
- ["cave"] = {rank="silver", upper="Silver"},
- ["nether"] = {rank="gold", upper="Gold"},
- }
- local rank = ranks[currentgame].rank
- local upperank = ranks[currentgame].upper
-
-
- local tokencount = 1
- local startpos = minetest.string_to_pos(survivalist.modstorage:get_string(pname .. ":pos"))
-
-
- if startpos then
- local dist = vector_distance(finalcitypos, startpos)
-
- dist = dist - 10000
-
-
- dist = math_floor(dist / 1000)
-
- if dist < 1 then
- dist = 1
- end
- tokencount = dist
- end
-
- local dname = rename.gpn(pname)
- if not gdac.player_is_admin(pname) then
- minetest.chat_send_all("# Server: Player <" .. dname .. "> has claimed victory in the " .. cityname .. "!")
- minetest.chat_send_all("# Server: Player <" .. dname .. ">'s skill has been tested in a Survival Challenge and proved worthy.")
- minetest.chat_send_all("# Server: Player <" .. dname .. "> has earned " .. tokencount .. " " .. upperank .. " Skill Mark(s).")
- else
- minetest.chat_send_player(pname, "# Server: You have won the Survival Challenge!")
- end
- local inv = player:get_inventory()
- local leftover = inv:add_item("main", ItemStack("survivalist:" .. rank .. "_skill_token " .. tokencount))
-
-
- if leftover:get_count() > 0 then
- minetest.item_drop(leftover, player, pos)
- if not gdac.player_is_admin(pname) then
- minetest.chat_send_all("# Server: Player <" .. dname .. ">'s Skill Mark was dropped on the ground!")
- end
- end
- minetest.chat_send_player(pname, "# Server: You should have received a skill mark in your inventory. If your inventory was full, check near your feet!")
-
-
- survivalist.modstorage:set_string(pname .. ":mode", nil)
- survivalist.modstorage:set_string(pname .. ":pos", nil)
- survivalist.modstorage:set_string(pname .. ":home", nil)
- survivalist.modstorage:set_string(pname .. ":xp", nil)
- survivalist.players[pname].choice = nil
-
-
- local ms = survivalist.modstorage
- local wins_total = pname .. ":wins_total"
- local wins_streak = pname .. ":wins_streak"
- local wins_bstreak = pname .. ":wins_bstreak"
- local wins_type = pname .. ":wins_" .. currentgame
- local wins_tokens = pname .. ":wins_tokens"
- ms:set_int(wins_total, ms:get_int(wins_total) + 1)
- ms:set_int(wins_streak, ms:get_int(wins_streak) + 1)
- ms:set_int(wins_type, ms:get_int(wins_type) + 1)
- ms:set_int(wins_tokens, ms:get_int(wins_tokens) + tokencount)
-
-
-
- if ms:get_int(wins_streak) > ms:get_int(wins_bstreak) then
- ms:set_int(wins_bstreak, ms:get_int(wins_streak))
- end
-
-
-
- if currentgame == "surface" then
- if not minetest.check_player_privs(player, {big_hotbar=true}) then
- local privs = minetest.get_player_privs(pname)
- privs.big_hotbar = true
- minetest.set_player_privs(pname, privs)
- minetest.notify_authentication_modified(pname)
-
- player:hud_set_hotbar_image("gui_hotbar2.png")
- player:hud_set_hotbar_itemcount(16)
- end
- end
-
-
- survivalist.shout_player_stats(pname)
-
-
- survivalist.add_player_to_rankings(pname)
- end
- function survivalist.player_beat_cave_challenge(pname)
- local ms = survivalist.modstorage
- local va = ms:get_int(pname .. ":wins_cave") or 0
- if va > 0 then
- return true
- end
- return false
- end
- function survivalist.player_beat_nether_challenge(pname)
- local ms = survivalist.modstorage
- local va = ms:get_int(pname .. ":wins_nether") or 0
- if va > 0 then
- return true
- end
- return false
- end
- function survivalist.on_joinplayer(player)
- local pname = player:get_player_name()
- survivalist.players[pname] = {}
- minetest.after(0.5, function()
- local player = minetest.get_player_by_name(pname)
- if not player then
- return
- end
- local gamemode = survivalist.modstorage:get_string(pname .. ":mode")
- if gamemode == "surface" or gamemode == "cave" or gamemode == "nether" then
- local dname = rename.gpn(pname)
- if not gdac.player_is_admin(pname) then
- minetest.chat_send_all("# Server: Player <" .. dname .. "> is engaged in a Survival Challenge.")
- end
- minetest.chat_send_player(pname, "# Server: You are in a Survival Challenge. Avoid death by sleeping!")
- minetest.chat_send_player(pname, "# Server: Find the Surface Colony or the Nether City and claim victory in the Central Square to beat the Challenge.")
- end
- end)
- end
- function survivalist.on_dieplayer(player)
- local pname = player:get_player_name()
-
- if beds.has_respawn_bed(pname) then
- if survivalist.game_in_progress(pname) then
- minetest.after(1, function()
- minetest.chat_send_player(pname, "# Server: You should respawn in your bed. Warning: if you die without a bed, you will fail the Challenge.")
- end)
- end
- return
- end
- local gamemode = survivalist.modstorage:get_string(pname .. ":mode")
- if gamemode == "surface" or gamemode == "cave" or gamemode == "nether" then
-
- minetest.after(1, function()
- if not gdac.player_is_admin(pname) then
- local dname = rename.gpn(pname)
- minetest.chat_send_all("# Server: Player <" .. dname .. ">'s survival skill was tested and found wanting!")
- end
- survivalist.shout_player_stats(pname)
- minetest.chat_send_player(pname, "# Server: You failed the Survivalist Challenge. No goodies for you!")
- end)
-
- survivalist.modstorage:set_string(pname .. ":mode", nil)
- survivalist.modstorage:set_string(pname .. ":pos", nil)
- survivalist.modstorage:set_string(pname .. ":home", nil)
- survivalist.modstorage:set_string(pname .. ":xp", nil)
- survivalist.modstorage:set_int(pname .. ":wins_streak", 0)
-
-
- local ms = survivalist.modstorage
- local ff = pname .. ":wins_fail"
- ms:set_int(ff, ms:get_int(ff) + 1)
-
-
- survivalist.add_player_to_rankings(pname)
- end
- end
- function survivalist.abort_game(pname)
- local player = minetest.get_player_by_name(pname)
- if not player or not player:is_player() then
- return
- end
- local pmeta = player:get_meta()
- local gamemode = survivalist.modstorage:get_string(pname .. ":mode")
- if gamemode == "surface" or gamemode == "cave" or gamemode == "nether" then
- if not survivalist.check_inventories_empty(pname) then
- minetest.chat_send_player(pname, "# Server: All your inventories (including the Starfissure Box and armor) must be empty before you may cancel a challenge (the Proof of Citizenship does not count).")
- easyvend.sound_error(pname)
- return
- end
- minetest.chat_send_player(pname, "# Server: Challenge termination confirmed.")
- local target = rc.static_spawn("abyss")
- target = minetest.string_to_pos(survivalist.modstorage:get_string(pname .. ":home")) or target
-
- local pcb = function()
- if not survivalist.check_inventories_empty(pname) then
- minetest.chat_send_player(pname, "# Server: All your inventories (including the Starfissure Box and armor) must be empty before you may cancel a challenge (the Proof of Citizenship does not count).")
- easyvend.sound_error(pname)
-
-
- return true
- end
-
- if default.player_attached[pname] then
- minetest.chat_send_player(pname, "# Server: Transport error. Player attached!")
- return true
- end
- end
-
- local bcb = function()
-
-
- survivalist.modstorage:set_string(pname .. ":mode", nil)
- survivalist.modstorage:set_string(pname .. ":pos", nil)
- survivalist.modstorage:set_string(pname .. ":home", nil)
- survivalist.modstorage:set_string(pname .. ":xp", nil)
-
-
-
-
-
-
-
-
-
-
-
- local bedpos = minetest.string_to_pos(pmeta:get_string("survivalist_old_bed_pos"))
- if bedpos then
- beds.set_player_spawn(pname, bedpos)
- end
- pmeta:set_string("survivalist_old_bed_pos", "")
- if not gdac.player_is_admin(pname) then
- local dname = rename.gpn(pname)
- minetest.chat_send_all("# Server: Player <" .. dname .. "> canceled a Survival Challenge and went home.")
- else
- minetest.chat_send_player(pname, "# Server: You canceled a Survival Challenge and went home.")
- end
- beds.report_respawn_status(pname)
- end
-
- preload_tp.execute({
- player_name = pname,
- target_position = target,
- emerge_radius = 32,
- pre_teleport_callback = pcb,
- post_teleport_callback = bcb,
- force_teleport = true,
- send_blocks = true,
- particle_effects = true,
- })
- else
- minetest.chat_send_player(pname, "# Server: You are not in a Survival Challenge; cannot abort.")
- easyvend.sound_error(pname)
- end
- end
- function survivalist.compose_formspec(pname)
- local modestring = ""
- local inchallenge = false
- local gamemode = survivalist.modstorage:get_string(pname .. ":mode")
- if gamemode == "surface" then
- modestring = " (You are currently in an Iceworld Challenge)"
- inchallenge = true
- elseif gamemode == "cave" then
- modestring = " (You are currently in an Underearth Challenge)"
- inchallenge = true
- elseif gamemode == "nether" then
- modestring = " (You are currently in a Netherealm Challenge)"
- inchallenge = true
- end
-
- local type_surface = "false"
- local type_cave = "false"
- local type_nether = "false"
-
-
- if survivalist.players[pname] and survivalist.players[pname].choice then
- local choice = survivalist.players[pname].choice
- if choice == "surface" then
- type_surface = "true"
- elseif choice == "cave" then
- type_cave = "true"
- elseif choice == "nether" then
- type_nether = "true"
- end
- end
-
- local formspec = ""
- formspec = formspec .. "size[8,7]" ..
- default.gui_bg ..
- default.gui_bg_img ..
- default.gui_slots ..
-
- "label[0,0;Survivalist Challenge" .. modestring .. "]" ..
-
- "textarea[0.3,0.5;8,4;rules;;" .. minetest.formspec_escape(survivalist.gamerules) .. "]"
-
-
- if not inchallenge and survivalist.have_xp(pname, "minimum") then
- formspec = formspec .. "label[0,4;Choose Your Challenge!]"
- if survivalist.have_xp(pname, "surface") then
- formspec = formspec .. "checkbox[0,4.3;type_surface;Surface Survival (Copper Mark);" .. type_surface .. "]"
- end
- if survivalist.have_xp(pname, "cave") then
- formspec = formspec .. "checkbox[0,4.8;type_cave;Cave Survival (Silver Mark);" .. type_cave .. "]"
- end
- if survivalist.have_xp(pname, "nether") then
- formspec = formspec .. "checkbox[0,5.3;type_nether;Nether Survival (Gold Mark);" .. type_nether .. "]"
- end
- end
-
- if inchallenge then
- formspec = formspec .. "button[0,6.2;2,1;abort;Go Home]"
- else
- if survivalist.have_xp(pname, "minimum") then
- formspec = formspec .. "button[0,6.2;3,1;start;Begin Challenge]"
- end
- end
-
- if inchallenge then
- formspec = formspec .. "button[2,6.2;2,1;victory;Claim Victory]"
- end
- formspec = formspec .. "button[4,6.2;2,1;show_rankings;Rankings]" ..
- "button[6,6.2;2,1;close;Close]"
- return formspec
- end
- function survivalist.compose_rankings_formspec(pname)
- local players = survivalist.get_ranking_entries()
- local data = {}
-
- local ms = survivalist.modstorage
- for k, v in pairs(players) do
- data[#data+1] = {
- name = k,
- wins = ms:get_int(k .. ":wins_total"),
- deaths = ms:get_int(k .. ":wins_fail"),
- streak = ms:get_int(k .. ":wins_streak"),
- bstreak = ms:get_int(k .. ":wins_bstreak"),
- surface = ms:get_int(k .. ":wins_surface"),
- cave = ms:get_int(k .. ":wins_cave"),
- nether = ms:get_int(k .. ":wins_nether"),
- tokens = ms:get_int(k .. ":wins_tokens"),
- }
- end
-
- local form = ""
- form = form .. "size[13,7]" ..
- default.gui_bg ..
- default.gui_bg_img ..
- default.gui_slots ..
- "label[0,0;Survival Challenge Rankings]" ..
- "button[11,6.2;2,1;close_rankings;Close]"
-
- form = form .. "tablecolumns[color;text;text;text;text;text;text;text;text;text;text;text;text;text;text;text;text;text]"
- form = form .. "table[0,0.5;12.8,5;rankings_table;"
- form = form .. "#00ffff,Username,|,Victories,|,Deaths,|,C-Streak,|,B-Streak,|,Iceworld,|,Underearth,|,Netherealm,|,Marks,"
-
- for k, v in ipairs(data) do
- form = form .. ",<" .. rename.gpn(v.name) .. ">,|," .. v.wins .. ",|," .. v.deaths .. ",|," ..
- v.streak .. ",|," .. v.bstreak .. ",|," .. v.surface .. ",|," .. v.cave ..
- ",|," .. v.nether .. ",|," .. v.tokens .. ","
- end
-
- form = string.gsub(form, ",$", "")
- form = form .. ";1]"
-
- return form
- end
- function survivalist.show_rankings_formspec(pname)
- local formspec = survivalist.compose_rankings_formspec(pname)
- minetest.show_formspec(pname, "survivalist:rankings", formspec)
- end
- function survivalist.show_formspec(pname)
- local formspec = survivalist.compose_formspec(pname)
- minetest.show_formspec(pname, "survivalist:survivalist", formspec)
- end
- function survivalist.on_receive_fields(player, formname, fields)
- local pname = player:get_player_name()
- if formname ~= "survivalist:survivalist" and formname ~= "survivalist:rankings" then
- return
- end
- if fields.quit then
- return true
- end
-
- if fields.show_rankings then
- survivalist.show_rankings_formspec(pname)
- return true
- end
- if fields.rankings_table then
- survivalist.show_rankings_formspec(pname)
- return true
- end
-
- if fields.close_rankings or formname == "survivalist:rankings" then
- survivalist.show_formspec(pname)
- return true
- end
-
-
- if fields.start and survivalist.have_xp(pname, "minimum") then
- minetest.close_formspec(pname, "survivalist:survivalist")
- survivalist.start_game(pname, survivalist.players[pname].choice)
- return true
- end
-
-
- if fields.victory then
- minetest.close_formspec(pname, "survivalist:survivalist")
- survivalist.attempt_claim(pname)
- return true
- end
-
- if fields.abort then
- minetest.close_formspec(pname, "survivalist:survivalist")
- survivalist.abort_game(pname)
- return true
- end
-
-
- for j, k in ipairs({"surface", "cave", "nether"}) do
- if fields["type_" .. k] then
- if fields["type_" .. k] == "true" then
- survivalist.players[pname].choice = k
- else
- survivalist.players[pname].choice = nil
- end
- survivalist.show_formspec(pname)
- return true
- end
- end
-
- if fields.close then
-
- passport.show_formspec(pname)
- return true
- end
-
- survivalist.show_formspec(pname)
- return true
- end
- if not survivalist.run_once then
-
- survivalist.modstorage = minetest.get_mod_storage()
-
- minetest.register_privilege("big_hotbar", {
- description = "Player has double-wide hotbar for item wielding.",
- give_to_singleplayer = false,
- })
-
-
-
- local nodebox = {
- type = "fixed",
- fixed = {
- {-0.5, -0.5, -0.5, 0.5, -15/32, 0.5},
- },
- }
- for j, k in ipairs({
- {name="copper", upper="Copper"},
- {name="silver", upper="Silver"},
- {name="gold", upper="Gold"},
- }) do
- minetest.register_node("survivalist:" .. k.name .. "_skill_token", {
- description = k.upper .. " Skill Mark",
- tiles = {"survivalist_" .. k.name .. "_token.png"},
- inventory_image = "survivalist_" .. k.name .. "_token.png",
- wield_image = "survivalist_" .. k.name .. "_token.png",
-
-
-
- paramtype = "light",
- paramtype2 = "facedir",
- sunlight_propagates = true,
- walkable = false,
- groups = utility.dig_groups("item"),
- sounds = default.node_sound_metal_defaults(),
- drawtype = "nodebox",
- node_box = nodebox,
- selection_box = nodebox,
- on_place = minetest.rotate_node,
- })
- end
-
- minetest.register_alias("survivalist:skill_token", "survivalist:silver_skill_token")
-
-
-
- minetest.register_on_player_receive_fields(function(...)
- return survivalist.on_receive_fields(...)
- end)
-
-
- minetest.register_on_joinplayer(function(...)
- return survivalist.on_joinplayer(...)
- end)
-
- minetest.register_on_dieplayer(function(...)
- return survivalist.on_dieplayer(...)
- end)
-
-
-
- local c = "survivalist:core"
- local f = survivalist.modpath .. "/init.lua"
- reload.register_file(c, f, false)
-
-
- survivalist.run_once = true
- end
|