book write: bugfix

item drops: randomize number of returned items
too long code used fix
master
rnd 2019-01-27 18:40:29 +01:00
parent 5706500ad8
commit ac1817dc9e
5 changed files with 206 additions and 135 deletions

View File

@ -457,10 +457,11 @@ basic_robot.commands.write_book = function(name,title,text) -- returns itemstack
local data = {}
if title == "" or not title then title = "program book "..minetest.get_gametime() end
data.title = title
data.title = title or ""
data.text = text or ""
data.text_len = #data.text
data.page = 1
data.description = title or ""
data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp)
data.owner = name
--local data_str = minetest.serialize(data) -- pre 0.4.16
@ -484,15 +485,16 @@ basic_robot.give_drops = function(nodename, inv) -- gives apropriate drops when
if max_items==0 then -- just drop all the items (taking the rarity into consideration)
max_items = #table.drop.items or 0;
end
max_items = math.random(max_items) -- return random number of items
local drop = table.drop;
local i = 0;
for k,v in pairs(drop.items) do
if i > max_items then break end; i=i+1;
if i > max_items then break end;
i=i+1;
local rare = v.rarity or 1;
if rare>0 and math.random(1, rare)==1 then
dropname = v.items[math.random(1,#v.items)]; -- pick item randomly from list
inv:add_item("main",dropname);
break
end
end
else

View File

@ -209,7 +209,7 @@ function getSandboxEnv (name)
label = function(text)
local obj = basic_robot.data[name].obj;
obj:set_properties({nametag = text}); -- "[" .. name .. "] " ..
obj:set_properties({nametag = text or ""}); -- "[" .. name .. "] " ..
end,
display_text = function(text,linesize,size)
@ -1578,6 +1578,7 @@ minetest.register_on_player_receive_fields(
if not data then data = {} end
local text = fields.book or "";
if string.len(text) > 64000 then
local sender = player:get_player_name();
minetest.chat_send_all("#ROBOT: " .. sender .. " is spamming with long text.") return
end
data.text = text or ""

View File

@ -11,6 +11,22 @@ if not paste then
end
end
data = {};
display_marker = function(pos,label)
minetest.add_particle(
{
pos = pos,
expirationtime = 10,
velocity = {x=0, y=0,z=0},
size = 18,
texture = label..".png",
acceleration = {x=0,y=0,z=0},
collisiondetection = true,
collision_removal = true,
})
end
self.listen(1)
self.label("COPY-PASTE MASTER v1.2 gold edition. commands: c1 c2 r c p")
end
@ -21,12 +37,16 @@ speaker, msg = self.listen_msg()
if speaker == "rnd" then
local player = _G.minetest.get_player_by_name(speaker);
local p = player:getpos(); p.x = round(p.x); p.y=round(p.y); p.z = round(p.z);
if p.y<0 then p.y = p.y +1 end -- needed cause of minetest bug
if msg == "c1" then
paste.src1 = {x=p.x,y=p.y,z=p.z};say("marker 1 set at " .. p.x .. " " .. p.y .. " " .. p.z)
display_marker(p,"099") -- c
elseif msg == "c2" then
paste.src2 = {x=p.x,y=p.y,z=p.z};say("marker 2 set at " .. p.x .. " " .. p.y .. " " .. p.z)
display_marker(p,"099") -- c
elseif msg == "r" then
paste.ref = {x=p.x,y=p.y,z=p.z};say("reference set at " .. p.x .. " " .. p.y .. " " .. p.z)
display_marker(p,"114") -- r
elseif msg == "c" then -- copy
local x1 = math.min(paste.src1.x,paste.src2.x);local y1 = math.min(paste.src1.y,paste.src2.y);local z1 = math.min(paste.src1.z,paste.src2.z);
local x2 = math.max(paste.src1.x,paste.src2.x);local y2 = math.max(paste.src1.y,paste.src2.y);local z2 = math.max(paste.src1.z,paste.src2.z);

View File

@ -1,137 +1,146 @@
-- simple ctf robot, rnd
--instructions: build game arena and place blue/red buttons as flags. edit flag positions below
--you must register 'keyboard' events by placing robot with same 'id' as robot running this code at 'event register' positions - default (32*i,64*j+1, 32*k)
-- simple ctf robot, rnd
--instructions: build game arena and place blue/red buttons as flags. edit flag positions below
--you must register 'keyboard' events by placing robot with same 'id' as robot running this code at 'event register' positions - default (32*i,64*j+1, 32*k)
if not ctf then
_G.minetest.forceload_block(self.pos(),true)
ctf = {
[1] = {state = 1, flagnode = "basic_robot:button8080FF", pos = {x=-18,y=501,z=17}, name = "blue", owner = "", score = 0}, -- team[1]
[2] = {state = 1, flagnode = "basic_robot:buttonFF8080", pos = {x=-79,y=501,z=46}, name = "red", owner = "", score = 0}, -- team[2]
}
teams = {} -- example : {["rnd"] = {1,0, player, health points at start}}; -- team, ownership of flag
maxscore = 3;
t = 0
teamid = 1; -- team selector when joining
gamestate = 0;
self.listen(1)
self.spam(1)
get_id = function(pos)
local range = 1000;
return pos.x + range*pos.y+range^2*pos.z
end
flag_id = {}; for i = 1,#ctf do flag_id[get_id(ctf[i].pos)] = i end
render_flags = function()
for i = 1,#ctf do minetest.set_node(ctf[i].pos, {name = ctf[i].flagnode}) end
end
end
if gamestate == 0 then -- welcome
say(colorize("red","#CAPTURE THE FLAG GAME. say '\\join' to join game. to start game one of joined players says '\\start'"))
gamestate = 1
elseif gamestate == 1 then
speaker,msg = self.listen_msg()
if msg == "join" then
local pl = minetest.get_player_by_name(speaker);
teams[speaker] = {teamid, 0, pl,20};pl:set_hp(20)
local msg1 = ""; local msg2 = ""
for k,v in pairs(teams) do
if v[1] == 1 then msg1 = msg1 .. k .. " " elseif v[1] == 2 then msg2 = msg2 .. k .. " " end
if not ctf then
_G.minetest.forceload_block(self.pos(),true)
ctf = {
[1] = {state = 1, flagnode = "basic_robot:button8080FF", pos = {x=-18,y=502,z=110}, name = "blue", owner = "", score = 0}, -- team[1]
[2] = {state = 1, flagnode = "basic_robot:buttonFF8080", pos = {x=-18,y=502,z=80}, name = "red", owner = "", score = 0}, -- team[2]
}
teams = {} -- example : {["rnd"] = {1,0, player, health points at start}}; -- team, ownership of flag
maxscore = 3;
t = 0
teamid = 1; -- team selector when joining
gamestate = 0;
self.listen(1)
self.spam(1)
get_id = function(pos)
local range = 1000;
return pos.x + range*pos.y+range^2*pos.z
end
say(colorize("yellow","#CTF : " .. speaker .. " joined team " .. ctf[teamid].name .. ". TEAM " .. ctf[1].name .. ": " .. msg1 .. ", TEAM " .. ctf[2].name .. ": " .. msg2))
teamid = 3-teamid; -- 1,2
elseif msg == "start" then -- game start
if teams[speaker] then
gamestate = 2
keyboard.get() -- clear keyboard buffer
say(colorize("red","#CTF GAME STARTED. GET ENEMY FLAG AND BRING IT BACK TO YOUR FLAG. DONT LET YOUR HEALTH GO BELOW 5 HEARTS OR YOU ARE OUT."))
for k,_ in pairs(teams) do -- teleport players
local data = teams[k];data[3]:setpos( ctf[data[1]].pos )
end
render_flags()
flag_id = {}; for i = 1,#ctf do flag_id[get_id(ctf[i].pos)] = i end
render_flags = function()
for i = 1,#ctf do minetest.set_node(ctf[i].pos, {name = ctf[i].flagnode}) end
end
end
elseif gamestate == 2 then
-- check player health
for k,v in pairs(teams) do
local hp = teams[k][3]:get_hp();
if not hp or hp<10 then -- teams[k][4]
local cflag = teams[k][2];
if cflag>0 then -- drop flag
ctf[cflag].state = 1
ctf[cflag].owner = ""
minetest.set_node(ctf[cflag].pos, {name = ctf[cflag].flagnode})
say(colorize("red", "#CTF " .. k .. " dropped " .. ctf[cflag].name .. " flag!"))
if gamestate == 0 then -- welcome
say(colorize("red","#CAPTURE THE FLAG GAME. say '\\join' to join game. to start game one of joined players says '\\start'"))
gamestate = 1
elseif gamestate == 1 then
speaker,msg = self.listen_msg()
if msg == "join" then
local pl = minetest.get_player_by_name(speaker);
teams[speaker] = {teamid, 0, pl,20};pl:set_hp(20)
local msg1 = ""; local msg2 = ""
for k,v in pairs(teams) do
if v[1] == 1 then msg1 = msg1 .. k .. " " elseif v[1] == 2 then msg2 = msg2 .. k .. " " end
end
if not hp then -- player left
say(colorize("yellow", "#CTF " .. k .. " left the game!"))
teams[k] = nil
else -- reset player
say(colorize("yellow", "#CTF " .. k .. " resetted!"))
v[2] = 0 -- player has no flag
v[3]:set_hp(20)
v[3]:setpos( ctf[v[1]].pos )
end
say(colorize("yellow","#CTF : " .. speaker .. " joined team " .. ctf[teamid].name .. ". TEAM " .. ctf[1].name .. ": " .. msg1 .. ", TEAM " .. ctf[2].name .. ": " .. msg2))
teamid = 3-teamid; -- 1,2
elseif msg == "start" then -- game start
if teams[speaker] then
gamestate = 2
keyboard.get() -- clear keyboard buffer
say(colorize("red","#CTF GAME STARTED. GET ENEMY FLAG AND BRING IT BACK TO YOUR FLAG. DONT LET YOUR HEALTH GO BELOW 3 HEARTS OR YOU ARE OUT."))
for k,_ in pairs(teams) do -- teleport players
local data = teams[k];data[3]:setpos( ctf[data[1]].pos )
end
render_flags()
end
end
end
event = keyboard.get()
if event and teams[event.puncher] then
--say(serialize(event))
local punch_id = get_id({x=event.x,y=event.y,z=event.z});
local flag = flag_id[punch_id];
if flag then
local state = ctf[flag].state
local puncher = event.puncher;
if state == 1 then -- flag is here, ready to be taken or capture of enemy flag
if teams[puncher][1] ~= flag then -- take
say(colorize("red","#CTF " .. puncher .. " has taken " .. ctf[flag].name .. " flag !"))
ctf[flag].state = 2;
ctf[flag].owner = puncher;
teams[puncher][2] = flag;
minetest.set_node(ctf[flag].pos, {name = "basic_robot:buttonFFFF80"})
else -- capture?
if teams[puncher][2] > 0 then
local cflag = teams[puncher][2] -- puncher has this flag
local data = ctf[cflag];
local team = teams[puncher][1];
ctf[team].score = ctf[team].score + 1
ctf[team].owner = ""
ctf[cflag].state = 1; -- reset captured flag state
minetest.set_node(ctf[cflag].pos, {name = ctf[cflag].flagnode})
teams[puncher][2] = 0
say(colorize("orange","#CTF " .. puncher .. " has captured " .. data.name .. " flag! Team " .. ctf[team].name .. " has score " .. ctf[team].score ))
if ctf[team].score == maxscore then
say(colorize("yellow","#CTF: TEAM " .. ctf[team].name .. " WINS! "))
gamestate = 3;t=5; -- intermission, duration 5
--reset
teams = {}
for i=1,#ctf do ctf[i].state = 1 ctf[i].score = 0 ctf[i].owner = "" end
end
end
elseif gamestate == 2 then
speaker,msg = self.listen_msg()
if msg == "score" then
local msg1 = ""; local msg2 = ""
for k,v in pairs(teams) do
if v[1] == 1 then msg1 = msg1 .. k .. " " elseif v[1] == 2 then msg2 = msg2 .. k .. " " end
end
say(colorize("yellow","SCORE " .. ctf[1].score .. "/" .. ctf[2].score) .."\n" .. colorize("yellow","TEAM " .. ctf[1].name .. ": " .. msg1 .. ", TEAM " .. ctf[2].name .. ": " .. msg2))
end
-- check player health
for k,v in pairs(teams) do
local hp = teams[k][3]:get_hp();
if not hp or hp<6 then -- teams[k][4]
local cflag = teams[k][2];
if cflag>0 then -- drop flag
ctf[cflag].state = 1
ctf[cflag].owner = ""
minetest.set_node(ctf[cflag].pos, {name = ctf[cflag].flagnode})
say(colorize("red", "#CTF " .. k .. " dropped " .. ctf[cflag].name .. " flag!"))
end
if not hp then -- player left
say(colorize("yellow", "#CTF " .. k .. " left the game!"))
teams[k] = nil
else -- reset player
say(colorize("yellow", "#CTF " .. k .. " resetted!"))
v[2] = 0 -- player has no flag
v[3]:set_hp(20)
v[3]:setpos( ctf[v[1]].pos )
end
end
end
--say(serialize(event))
end
elseif gamestate == 3 then -- intermission
if t>0 then t=t-1 else gamestate = 0 end
end
event = keyboard.get()
if event and teams[event.puncher] then
--say(serialize(event))
local punch_id = get_id({x=event.x,y=event.y,z=event.z});
local flag = flag_id[punch_id];
if flag then
local state = ctf[flag].state
local puncher = event.puncher;
if state == 1 then -- flag is here, ready to be taken or capture of enemy flag
if teams[puncher][1] ~= flag then -- take
say(colorize("red","#CTF " .. puncher .. " has taken " .. ctf[flag].name .. " flag !"))
ctf[flag].state = 2;
ctf[flag].owner = puncher;
teams[puncher][2] = flag;
minetest.set_node(ctf[flag].pos, {name = "basic_robot:buttonFFFF80"})
else -- capture?
if teams[puncher][2] > 0 then
local cflag = teams[puncher][2] -- puncher has this flag
local data = ctf[cflag];
local team = teams[puncher][1];
ctf[team].score = ctf[team].score + 1
ctf[team].owner = ""
ctf[cflag].state = 1; -- reset captured flag state
minetest.set_node(ctf[cflag].pos, {name = ctf[cflag].flagnode})
teams[puncher][2] = 0
say(colorize("orange","#CTF " .. puncher .. " has captured " .. data.name .. " flag! Team " .. ctf[team].name .. " has score " .. ctf[team].score ))
if ctf[team].score == maxscore then
say(colorize("yellow","#CTF: TEAM " .. ctf[team].name .. " WINS! "))
gamestate = 3;t=5; -- intermission, duration 5
--reset
teams = {}
for i=1,#ctf do ctf[i].state = 1 ctf[i].score = 0 ctf[i].owner = "" end
end
end
end
end
end
--say(serialize(event))
end
elseif gamestate == 3 then -- intermission
if t>0 then t=t-1 else gamestate = 0 end
end

View File

@ -4,6 +4,10 @@ if not data then
paused = true
turn = 2;
turntimeout = 5
shorttimeout = 1
shortround = false
turnmessage = ""
t = 0;
SIGNUP = 0; GAME = 1; INTERMISSION = 2
state = SIGNUP
@ -12,6 +16,8 @@ if not data then
data = {};
init_game = function()
abilitypoints = {0,0}; -- points to use ability, step outside ring to use them in following round
shortround = false
data = {}; minescount = 32
for i = 1, minescount do local i = math.random(m); local j = math.random(n); if not data[i] then data[i] = {} end; data[i][j] = 1; end
if not data[1] then data[1] = {} end if not data[2] then data[2] = {} end -- create 2x2 safe area
@ -44,8 +50,17 @@ if not data then
return count
end
near_chat = function(msg)
end
greeting = function()
_G.minetest.chat_send_all(colorize("red","#BATTLE MINESWEEPER : two player battle in minesweeper. say join to play.\nRules: 1. each player has 5 second turn to make a move 2. if you dont make move you lose\n3. if you make move in other player turn you lose. 4. if you hit bomb or mark bomb falsely you lose"))
_G.minetest.chat_send_all(colorize("red",
"#BATTLE MINESWEEPER : two player battle in minesweeper. say join to play.\nRules: "..
"1. each player has 5 second turn to make a move 2. if you dont make move you lose\n"..
"3. if you make move in other player turn you lose. 4. if you hit bomb or mark bomb falsely you lose\n"..
"5. by playing fast you get ability charge. when you collect 10 you can step out of ring when your round ends and opponent will only have 2s to play his turn."
))
end
player_lost = function ()
@ -53,22 +68,38 @@ if not data then
local player = _G.minetest.get_player_by_name(players[i]);
if player then player:setpos({x=spawnpos.x,y=spawnpos.y+10,z=spawnpos.z}) end
end
_G.minetest.sound_play("electric_zap",{pos=spawnpos, max_hear_distance = 100})
state = INTERMISSION; t = 0
end
function change_turn()
shortround = false -- reset ability if activated
if turn == 1 then
_G.minetest.sound_play("default_break_glass",{pos=spawnpos, max_hear_distance = 100})
else
_G.minetest.sound_play("note_a",{pos=spawnpos, max_hear_distance = 100})
_G.minetest.sound_play("default_cool_lava",{pos=spawnpos, max_hear_distance = 100})
end
if paused == false then
say(players[turn] .. " lost : didn't make a move");
say(players[turn] .. " lost : didn't make a move fast enough ");
player_lost()
else
local player = minetest.get_player_by_name(players[turn])
local ppos = player:getpos()
local x = ppos.x - spawnpos.x;local y = ppos.y - spawnpos.y;local z = ppos.z - spawnpos.z;
local points = abilitypoints[turn]
if x<1 or x>m or z<1 or z>n then -- outside area
local points = abilitypoints[turn]
if points>=10 then -- do we have enough points?
shortround = true -- next round will be shorter, 2s
_G.minetest.sound_play("grinder",{pos=spawnpos, max_hear_distance = 100})
abilitypoints[turn] = abilitypoints[turn]-10
end
end
if turn == 1 then turn = 2 else turn = 1 end
self.label("turn " .. turn .. " " .. players[turn])
turnmessage = "turn " .. turn .. " " .. players[turn] .. ",charge " .. abilitypoints[turn] .. "\n"
self.label(turnmessage)
t=0
paused = false
end
@ -96,6 +127,7 @@ if state == SIGNUP then
if player then player:setpos({x=spawnpos.x,y=spawnpos.y+1,z=spawnpos.z}) end
end
_G.minetest.chat_send_all(colorize("red","BATTLE MINESWEEPER " .. m .. "x" ..n .. " with " .. minescount .. " mines.\n" .. players[turn] .. " its your move!"))
init_game()
end
end
@ -104,17 +136,24 @@ if state == SIGNUP then
elseif state == GAME then
t = t + 1;
if t>5 then -- change of turn
if (t>turntimeout) or (shortround and t>shorttimeout) then -- change of turn
change_turn()
else
self.label(turnmessage .. " " .. (turntimeout-t+1))
end
event = keyboard.get();
if event and event.type == 2 and not paused then
if event.puncher == players[turn] then
local x = event.x - spawnpos.x;local y = event.y - spawnpos.y;local z = event.z - spawnpos.z;
if x<1 or x>m or z<1 or z>n then
local points = abilitypoints[turn]
if x<1 or x>m or z<1 or z>n then -- outside area
else
local ppos = player.getpos(event.puncher)
points = points + math.max(turntimeout-t-2,0); if points>40 then points = 40 end
abilitypoints[turn] = points
if ppos and math.abs(ppos.x-event.x)<0.5 and math.abs(ppos.z-event.z)<0.5 then -- just mark mine
if data[x] and data[x][z] == 1 then
if keyboard.read({x=event.x,y=event.y,z=event.z})~="basic_robot:button808080" then
@ -146,5 +185,5 @@ elseif state == GAME then
end
elseif state == INTERMISSION then
t=t+1; if t> 15 then state = SIGNUP;players = {}; paused = true; init_game(); greeting() end
t=t+1; if t> 15 then state = SIGNUP;players = {}; paused = true; greeting() end
end