diff options
| author | Alexander M Pickering <alex@cogarr.net> | 2024-01-29 16:20:10 -0600 |
|---|---|---|
| committer | Alexander M Pickering <alex@cogarr.net> | 2024-01-29 16:20:10 -0600 |
| commit | c2926c5ec74d7e37da395c8c32a7ff2b4cae7d06 (patch) | |
| tree | ac2bb208dab1274cdc5e9059ffe014ae19181a4c /src/world.moon | |
| download | fools_rush_in-c2926c5ec74d7e37da395c8c32a7ff2b4cae7d06.tar.gz fools_rush_in-c2926c5ec74d7e37da395c8c32a7ff2b4cae7d06.tar.bz2 fools_rush_in-c2926c5ec74d7e37da395c8c32a7ff2b4cae7d06.zip | |
All the files
Diffstat (limited to 'src/world.moon')
| -rw-r--r-- | src/world.moon | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/src/world.moon b/src/world.moon new file mode 100644 index 0000000..c7b106c --- /dev/null +++ b/src/world.moon @@ -0,0 +1,368 @@ +-- Handles singleton logic + +mod = ... +connect = require "connect" +lobby = require "lobby" +joined = require "joined" +party = require "party" +char = require "char" +import Character from char +import Enemy from char +import Party from party +player = require "player" +import RemotePlayer from player +import LocalPlayer from player +main = require "main" +room = require "room" +import Room from room +import LobbyRoom from room +ui = require "ui" +ability = require "ability_reg" + +class Server + new:() => + @server = true + @client = false + am.eval_js(connect) + am.eval_js(lobby) + @lobby_id = am.eval_js("GLOBAL.lobby_id") + @game_state = "lobby" --lobby, room_entry, room_players, room_battle_animate, victory, camp_entry, camp_players_animate, defeat, done + @game_state_extra = 0 + @players = {} --[peer_id] = tbl + @set_actions = {} --[peer_id] = "name" + @player_party = nil -- the party, created at campaign start + @host = nil --who is the lobby host, with the power to start the game? + @enemy_party = nil -- The enemy party + @updates = {} + @dead_players = {} --[peer_id] = true + @cr = 1 + player_joined:(msg)=> + peer = msg.peer + @players[peer] = RemotePlayer(peer,nil,char.classes.Tumbler) + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({msg:"info_player_joined",uname:peer,class:"Tumbler"}))) + if @host == nil + @host = peer + request_class_change:(msg)=> + if @game_state == "lobby" + if @players[msg.peer] + @players[msg.peer]\set_class(char.classes[msg.class]) + else + @players[msg.peer] = RemotePlayer(msg.peer,nil,char.classes[msg.class]) + am.eval_js(string.format("GLOBAL.send_message(%q,%q)",msg.peer,am.to_json({msg: "confirm_class_change", class: msg.class}))) + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({msg:"info_class_change",uname:msg.peer,class:msg.class}))) + else + am.eval_js(string.format("GLOBAL.send_message(%q,%q)",msg.peer,am.to_json({msg: "deny_class_change", class:@players[msg.peer].class}))) + request_campaign_start:(msg)=> + if msg.peer == @host and @game_state == "lobby" + @player_party = Party! + --Set everyone's position, hp, ect. + for _, chartbl in pairs(@players) + chartbl.position = chartbl.class.default_position + chartbl.hp = chartbl.class.default_hp + @player_party\add_member(chartbl) + @campaign_start! + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({msg:"info_campaign_start",time_ref:@player_start_time}))) + campaign_start: => + @game_state = "room_entry" + @player_start_time = am.eval_js("new Date().getTime()") + room = Room.generate(@cr) + @room = room + @enemy_party = @generate_enemies! + @enemy_party\set_room(room) + @player_party\set_room(room) + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({ + msg: "info_enemy_party", + data: @enemy_party\serialize! + }))) + room\distribute_party(@player_party,@enemy_party) + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({msg:"info_room",data:room\serialize!,time_ref:@player_start_time}))) + @game_state = "room_players" + + request_player_list:(msg)=> + player_ser = {} + for peerid, player in pairs(@players) + player_ser[peerid] = player\serialize! + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({msg:"respond_player_list", data:player_ser}))) + set_action: (msg)=> + if @game_state == "room_players" + if not @dead_players[msg.peer] + @set_actions[msg.peer] = ability[msg.action] + update:() => + msg = am.eval_js("GLOBAL.get_message()") + if msg != nil + if msg.msg == "data" + info = am.parse_json(msg.data) + info.peer = msg.peer -- server messages have an extra "peer" field that the client didn't add. + if @[info.msg] + @[info.msg](@,info) + else + print("Failed to find server message handler:",msg,"no handler",info.msg) + else + print("Msg was nil") + --actual game loop + if @game_state == "room_players" + if am.eval_js("new Date().getTime()") > @player_start_time + 6000 + --Generate some random actions from npcs + npc_actions = {} + used_actions = {} + party_index = {} + character_index = {} + for uname, npc in pairs(@enemy_party.members) + npc_actions[uname] = npc\select_action! + table.insert(used_actions, npc_actions[uname]) + party_index[npc_actions[uname]] = @enemy_party + character_index[npc_actions[uname]] = npc + total_actions = {} + for k,v in pairs(npc_actions) + total_actions[k] = v.__name + for k,v in pairs(@set_actions) + total_actions[k] = v.__name + table.insert(used_actions, v) + party_index[v] = @player_party + character_index[v] = @player_party\member(k) + --Lock in actions, and send it back out (500 ms) + table.sort(used_actions, (a,b) -> + a.speed < b.speed + ) + -- actually do the actions + for k,v in ipairs(used_actions) + tchar = character_index[v] + v.__class.use(@,party_index[v],tchar) + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({ + msg:"info_actions", + data: total_actions + }))) + --sort by speed and apply + @game_state = "room_battle_animate" + @set_actions = {} + if @game_state == "room_battle_animate" --only exists for 1 tick, calc dammge, check if room is done, check if we're defeated, ect. + @calculate_damage + @player_start_time = am.eval_js("new Date().getTime()")+500 --500 ms for animations + @game_state = "room_players" + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({ + msg:"info_timeref", + time_ref:@player_start_time + }))) + dead_characters = {} + for uname, char in pairs(@player_party.members) + if char.data.hp <= 0 + table.insert(dead_characters,uname) + char\die! + @player_party\remove_member(char) + @dead_players[uname] = true + for uname, char in pairs(@enemy_party.members) + if char.data.hp <= 0 + table.insert(dead_characters,uname) + char\die! + @enemy_party\remove_member(char) + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({ + msg:"info_deaths", + data:dead_characters + }))) + if @player_party\nmembers! == 0 + @game_state = "defeat" + elseif @enemy_party\nmembers! == 0 + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({ + msg:"info_loot" + time_ref:@player_start_time + --Don't actually do loot, just go to the next room + }))) + @player_start_time = am.eval_js("new Date().getTime()") + @game_state = "victory" + if @game_state == "defeat" + am.eval_js(string.format("GLOBAL.broadcast(%q)",am.to_json({ + msg:"info_defeat" + }))) + @game_state = "done" + if @game_state == "victory" + if am.eval_js("new Date().getTime()") > @player_start_time + 6000 -- a few seconds for victory! (and animations) + @cr += 1 + @campaign_start! + + calculate_dammage:() => + print("calculating dammage...") + + generate_enemies:() => + enemies = {} + tcr = @cr + possible_enemies = {} + for k,v in pairs(char.enemies) + table.insert(possible_enemies,v) + enemy_party = Party! + while tcr > 0 and #possible_enemies > 0 + filtered_enemies = {} + for _, enemy in pairs(possible_enemies) + if enemy.cr <= tcr + table.insert(filtered_enemies,enemy) + table.shuffle(filtered_enemies) + rng_enemy = table.remove(filtered_enemies) + tcr = tcr - rng_enemy.cr + enemy_party\add_member(Enemy(nil,rng_enemy)) + enemy_party + +class World + new:() => + @client = true + @server = false + am.eval_js(connect) + @players = {} + @player_party = Party! + @enemy_party = nil + main.root("world_characters")\append(@player_party.node) + @parties = {@player_party} + @node = am.group! + @node\append(@player_party.node) + @node\action(coroutine.create(()-> + while true + coroutine.yield! + )) + @localplayer = nil + join:(id) => + am.eval_js(joined) + am.eval_js("CLIENT.join('" .. id .. "');") + client_open:() => + am.eval_js("CLIENT.open") + client_id:() => + am.eval_js("CLIENT.peer") + confirm_class_change: (msg) => + @localplayer\set_class(char.classes[msg.class]) + deny_class_change: (msg) => + @localplayer\set_class(char.classes[msg.class]) + respond_player_list: (msg) => + for peerid, chardata in pairs(msg.data) + if not @player_party\member(peerid) + if peerid == am.eval_js("CLIENT.peer._id") + @localplayer = Character.deserialize(chardata) + @player_party\add_member(@localplayer) + @localplayer\enter_room(@player_party.room) + else + newplayer = Character.deserialize(chardata) + @player_party\add_member(newplayer) + newplayer\enter_room(@player_party.room) + else + print("Do nothing...") + info_class_change: (msg) => + if msg.uname == @localplayer.uname + return + if not @player_party\member(msg.uname) + @player_party\add_member(Character.deserialize(msg.class)) + else + @player_party\member(msg.uname)\set_class(char.classes[msg.class]) + info_player_joined: (msg) => + if msg.uname == am.eval_js("CLIENT.peer._id") + if @localplayer != nil + return + @localplayer = LocalPlayer(msg.uname, {}, char.classes[msg.class]) + @player_party\add_member(@localplayer) + @localplayer\enter_room(@player_party.room) + elseif not @player_party\member(msg.uname) + newplayer = RemotePlayer(msg.uname, nil, char.classes[msg.class]) + @player_party\add_member(newplayer) + newplayer\enter_room(@player_party.room) + else + print("Do nothing") + info_campaign_start: (msg) => + lobby_menu = require "lobby_menu" + create_party_menu = require "create_party_menu" + if create_party_menu.loaded + create_party_menu.unload! + if lobby_menu.loaded + lobby_menu.unload! + battle_menu = require "battle_menu" + battle_menu.load! + ui.fadeout! + @time_ref = msg.time_ref + info_room: (msg) => + @room = Room.deserialize(msg.data) + @time_ref = msg.time_ref + @set_room(@room) + battle_menu = require "battle_menu" + battle_menu.victory = false + main.root\remove("infocard") + info_timeref: (msg) => + main.root\remove("infocard") + @time_ref = msg.time_ref + info_enemy_party: (msg) => + if @enemy_party + @node\remove(@enemy_party.rnode) + @enemy_party = Party.deserialize(msg.data) + @enemy_party\set_room(@room) + if @room.__class != LobbyRoom + @enemy_party\set_room(@room) + battle_menu = require "battle_menu" + battle_menu.victory = false + main.root\remove("infocard") + --@node\append(@enemy_party.node) + info_defeat: (msg) => + battle_menu = require("battle_menu") + defeat_menu = require("defeat_menu") + table.insert(main.action_queue,{battle_menu.unload, {}}) + table.insert(main.action_queue,{defeat_menu.load,{}}) + info_loot: (msg) => + @time_ref = msg.time_ref + battle_menu = require "battle_menu" + battle_menu.victory = true + main.root\remove("infocard") + info_updates: (msg) => + for uname, updated in pairs(msg.data) + tchar = @player_party\member(uname) or @enemy_party\member(uname) + for k,v in pairs(updated) + tchar.data[k] = v + info_deaths: (msg) => + for _, uname in pairs(msg.data) + if @player_party\member(uname) + tchar = @player_party\member(uname) + tchar\die! + @player_party\remove_member(tchar) + elseif @enemy_party\member(uname) + tchar = @enemy_party\member(uname) + tchar\die! + @enemy_party\remove_member(tchar) + info_actions: (msg) => + for uname, action_name in pairs(msg.data) + action = ability[action_name] + if @player_party\member(uname) + action.use(@,@player_party,@player_party\member(uname)) + ui.battle_log(string.format("%s used %s",@player_party\member(uname).class.name,action.text)) + elseif @enemy_party\member(uname) + action.use(@,@enemy_party,@enemy_party\member(uname)) + ui.battle_log(string.format("%s used %s",uname,action.text)) + main.root\remove("infocard") + update: () => + msg = am.eval_js("CLIENT.get()") + if msg != nil + info = am.parse_json(msg) + if @[info.msg] + @[info.msg](@,info) + else + print("Failed to find client message handler", info) + set_local: (player) => + @localplayer = player + @player_party\add_member(player) + @localplayer\enter_room(@player_party.room) + set_room: (room) => + @room = room + assert(@room, "cannot set a nil room") + assert(@room.load, "rooms must have a .load") + if @player_party.room + @player_party.room\unload! + --@node\remove(@player_party.room.node) + @room\load! + --@node\append(room.node) + @player_party\set_room(room) + if @enemy_party + if @enemy_party.room + @enemy_party.room\unload! + @enemy_party\set_room(@room) + --new_rat = Enemy(nil,char.enemies.Rat) + if @enemy_party + --@enemy_party\add_member(new_rat) + --@enemy_party\set_room(room) + @node\append(@enemy_party.rnode) + load: () => + main.root("world_characters")\append(@node) + + +mod["World"] = World +mod["Server"] = Server +mod |
