var PORT = 8080; var gameMode = true; const mapWidth = 50; const mapHeight = 50; var allSockets = {}; var allPlayers = {}; var userCnt = 0; var express = require('express'); var app = express(); app.use(express.static(__dirname + '/')); var server = require('http').Server(app); var io = require('socket.io')(server); var map = require("./s_map.js"); var maxX = mapWidth * 32; var maxY = mapHeight * 32; var newmap = map.generateMap(mapWidth, mapHeight); let schatzversteckt = false; let schatzcoords = { x: 0, y: 0 }; while (!schatzversteckt) { for (var line = 0; line < newmap.cssMap.length; line++) { for (var column = 0; column < newmap.cssMap[line].length; column++) { if (newmap.cssMap[line][column] == "grass") { if (Math.random() < 0.1 && !schatzversteckt) { //console.log("versteckt", line, column) schatzcoords = { x: column, y: line }; //newmap.utilMap[line][column] = "item_item_schatz"; schatzversteckt = true console.log(schatzcoords, newmap.cssMap[line][column]) } } } } } //console.log(newmap.cssMap) var cssMap = newmap["cssMap"]; var map = newmap["map"]; var utilMap = newmap["utilMap"]; var defaultMvnt = 2; var itemAttrs = { "item_boots_boots1": { lvl: 1, changeMovementLand: 0.1 }, "item_boots_boots2": { lvl: 2, changeMovementLand: 0.15 }, "item_boots_boots3": { lvl: 3, changeMovementLand: 0.2 }, "item_boots_boots4": { lvl: 4, changeMovementLand: 0.25 }, "item_boots_boots5": { lvl: 5, changeMovementLand: 0.3 }, "item_tool_axe1": { lvl: 1, reduceTreeCutSpeed: 1 }, "item_tool_axe2": { lvl: 2, reduceTreeCutSpeed: 300 }, "item_tool_axe3": { lvl: 3, reduceTreeCutSpeed: 700 }, "item_tool_axe4": { lvl: 4, reduceTreeCutSpeed: 900 }, "item_tool_axe5": { lvl: 5, reduceTreeCutSpeed: 1300 }, "item_head_head1": { lvl: 1, armor: 10 }, "item_head_head2": { lvl: 2, armor: 18 }, "item_head_head3": { lvl: 3, armor: 23 }, "item_head_head4": { lvl: 4, armor: 25 }, "item_head_head5": { lvl: 5, armor: 30 }, "item_chest_chest1": { lvl: 1, armor: 10 }, "item_chest_chest2": { lvl: 2, armor: 18 }, "item_chest_chest3": { lvl: 3, armor: 23 }, "item_chest_chest4": { lvl: 4, armor: 25 }, "item_chest_chest5": { lvl: 5, armor: 30 }, "item_legs_legs1": { lvl: 1, armor: 10 }, "item_legs_legs2": { lvl: 2, armor: 18 }, "item_legs_legs3": { lvl: 3, armor: 23 }, "item_legs_legs4": { lvl: 4, armor: 28 }, "item_legs_legs5": { lvl: 5, armor: 30 }, "item_weapon_sword1": { lvl: 1, dmg: 40 }, "item_weapon_sword2": { lvl: 2, dmg: 60 }, "item_weapon_sword3": { lvl: 3, dmg: 80 }, "item_weapon_sword4": { lvl: 4, dmg: 100 }, "item_weapon_sword5": { lvl: 5, dmg: 130 }, "item_weapon_stick1": { lvl: 1, dmg: 20 }, "item_item_bone0": { lvl: 0, }, "item_item_seemen0": { lvl: 0, }, "item_item_spaten3": { lvl: 1, }, "item_item_schatz": { changeMovementSpeed: -0.5, lvl: -1, }, "item_consumable_fish1": { lvl: 3, hp: 30, }, "item_consumable_fish2": { lvl: 1, hp: 10 }, "item_item_woods1": { lvl: 1, //changeMovementSpeed: -0.5 }, } var items = []; for (var i in itemAttrs) { items.push(i) } server.listen(PORT); console.log("Pirate running on port:" + PORT); io.on('connection', function (socket) { var playerActionTimer = null; userCnt++; console.log("New user", socket.id); allSockets[socket.id] = socket; allPlayers[socket.id] = { keys: {}, x: 10, y: 10, mvnt: defaultMvnt, lookingLeft: 0, lookingUp: 0, special: {}, mode: 0, //0 = ship //1 foot slots: { head: null, chest: null, legs: null, boots: null, weapon: null, tool: null, item: null }, hp: 80, socketId: socket.id }; var player = allPlayers[socket.id]; io.sockets.emit("newPlayer", { player: allPlayers[socket.id], id: socket.id }); io.sockets.emit("setSchatzCoords", { schatzcoords: schatzcoords, }); socket.on('disconnect', function () { for (var i in player.slots) { if (player.slots[i]) { let nearFieldCoords = getNearEmptyField(Math.floor(player["x"] / 32), Math.floor(player["y"] / 32)); if (nearFieldCoords) { let newObj = { mapY: nearFieldCoords["y"], mapX: nearFieldCoords["x"], newName: player.slots[i] } utilMap[nearFieldCoords["y"]][nearFieldCoords["x"]] = newObj["newName"]; io.sockets.emit("dropItem", newObj); } } } userCnt--; delete allSockets[socket.id]; delete allPlayers[socket.id]; console.log("User Disconnected:", socket.id); io.sockets.emit("playerDisc", socket.id); }); socket.on('getmap', function () { newmap["allPlayers"] = allPlayers; socket.emit("getmap", newmap); }); socket.on('keyUp', function (key) { allPlayers[socket.id]["keys"][key] = false; if (key == 69 || key == 71) { //space oder G player["action"] = false; if (playerActionTimer) { clearTimeout(playerActionTimer); playerActionTimer = null; } io.sockets.emit("stopAction", socket.id); } }); socket.on('keyDown', function (key) { allPlayers[socket.id]["keys"][key] = true; if (key == 32 && allPlayers[socket.id]["mode"] != 0) { //Space HIT SOMEONE //if(allPlayers[socket.id]["mode"] == 1) { // On land if (!allPlayers[socket.id]["hitPending"]) { io.sockets.emit("showHitAnimation", socket.id); allPlayers[socket.id]["hitPending"] = true; let allPlayersWithCollision = checkHitWithOtherPlayers(socket.id); for (var i = 0; i < allPlayersWithCollision.length; i++) { calcDmgAndHitPlayer(allPlayers[socket.id], allPlayers[allPlayersWithCollision[i]]) } //console.log(allPlayersWithCollision); setTimeout(function () { allPlayers[socket.id]["hitPending"] = false; }, 500) } //} } else if (key == 71) { // Taste G var groundUnder = getGroundUnderPlayer(player["x"], player["y"]); let x = Math.floor(player["x"] / 32); let y = Math.round(player["y"] / 32); console.log("soso", map[y][x], y, x) if (map[y][x] == 6 || map[y][x] == 4 || map[y][x] == 5) { //its land let cutTime = 6000; //6 Secs if (player["slots"] && player["slots"]["item"] && player["slots"]["item"] == "item_item_spaten3") { cutTime = 2000; } if (playerActionTimer) { clearTimeout(playerActionTimer); playerActionTimer = null; } playerActionTimer = setTimeout(function () { let randomItem = getRandomItem(0, 0); //Drop a random Item if(schatzcoords["x"] == x && schatzcoords["y"] == y) { randomItem = "item_item_schatz" console.log("schatz!"); } let nearFieldCoords = getNearEmptyField(Math.floor(player["x"] / 32), Math.floor(player["y"] / 32)); utilMap[nearFieldCoords["y"]][nearFieldCoords["x"]] = randomItem; let newObj = { mapY: nearFieldCoords["y"], mapX: nearFieldCoords["x"], newName: randomItem } io.sockets.emit("dropItem", newObj); let newFloor = "sandhaufen"; if(map[y][x] == 6) { newFloor = "erdhaufen"; } io.sockets.emit("replaceFloor", { x: x, y: y, newFloor: newFloor }); cssMap[y][x] = "sandhaufen"; map[y][x] = 100; socket.emit("stopAnimation", cutTime); allPlayers[socket.id]["action"] = false; }, cutTime); allPlayers[socket.id]["action"] = true; socket.emit("animation", cutTime); } //console.log(groundUnder) } }); socket.on('actionKey', function (key) { var groundUnder = getGroundUnderPlayer(player["x"], player["y"]); if (key == 69) {// E if (player["mode"] == 0) { //ship if (groundUnder >= 1) { //its nearly land player["mode"] = 1; player["special"]["modechange"] = true; } } else { if (groundUnder <= 1) { //its water land player["mode"] = 0; player["special"]["modechange"] = true; } }; //console.log(player["mode"], groundUnder); var obj = getNearestObject(player["x"], player["y"]); if (obj) { obj["socketId"] = socket.id; if (playerActionTimer) { clearTimeout(playerActionTimer); playerActionTimer = null; } if (obj["name"] == "forest") { let cutTime = 2000; //2 Secs if (player["slots"]["tool"] && itemAttrs[player["slots"]["tool"]] && itemAttrs[player["slots"]["tool"]]["reduceTreeCutSpeed"] > 0) { cutTime -= itemAttrs[player["slots"]["tool"]]["reduceTreeCutSpeed"]; playerActionTimer = setTimeout(function () { if (Math.random() > 0.75) { utilMap[obj["mapY"]][obj["mapX"]] = "item_item_woods1"; obj["newName"] = "item_item_woods1"; io.sockets.emit("replaceUtil", obj); } else { utilMap[obj["mapY"]][obj["mapX"]] = ""; io.sockets.emit("removeUtil", obj); } socket.emit("stopAnimation", cutTime); }, cutTime); socket.emit("animation", cutTime); } else { socket.emit("displayMsg", "Baum kann nur mit einer Axt gefällt werden!"); //can not cut tree } } else if (obj["name"] == "treasure-closed") { playerActionTimer = setTimeout(function () { utilMap[obj["mapY"]][obj["mapX"]] = "treasure-open"; obj["newName"] = "treasure-open"; io.sockets.emit("replaceUtil", obj); socket.emit("stopAnimation", 2000); //Drop a random Item let randomItem = getRandomItem(2, 5); let nearFieldCoords = getNearEmptyField(obj["mapX"], obj["mapY"]); utilMap[nearFieldCoords["y"]][nearFieldCoords["x"]] = randomItem; let newObj = { mapY: nearFieldCoords["y"], mapX: nearFieldCoords["x"], newName: randomItem } io.sockets.emit("dropItem", newObj); }, 2000); //2 Secs socket.emit("animation", 2000); } else if (obj["name"] == "fass") { playerActionTimer = setTimeout(function () { utilMap[obj["mapY"]][obj["mapX"]] = ""; io.sockets.emit("removeUtil", obj); socket.emit("stopAnimation", 500); //Drop a random Item let randomItem = getRandomItem(1, 2); let nearFieldCoords = getNearEmptyField(obj["mapX"], obj["mapY"]); utilMap[nearFieldCoords["y"]][nearFieldCoords["x"]] = randomItem; let newObj = { mapY: nearFieldCoords["y"], mapX: nearFieldCoords["x"], newName: randomItem } io.sockets.emit("dropItem", newObj); }, 500); //2 Secs socket.emit("animation", 500); } else if (obj["name"].split("_")[0] == "item") { let itemName = obj["name"]; utilMap[obj["mapY"]][obj["mapX"]] = ""; io.sockets.emit("removeUtil", obj); let slotArt = obj["name"].split("_")[1]; if (allPlayers[socket.id]["slots"][slotArt]) { //Slot is not empty so drop it let nearFieldCoords = getNearEmptyField(Math.floor(player["x"] / 32), Math.floor(player["y"] / 32)); let newObj = { mapY: nearFieldCoords["y"], mapX: nearFieldCoords["x"], newName: allPlayers[socket.id]["slots"][slotArt] } utilMap[nearFieldCoords["y"]][nearFieldCoords["x"]] = newObj["newName"]; io.sockets.emit("dropItem", newObj); //console.log("drop", newObj) } if (slotArt == "consumable") { let hp = itemAttrs[obj["name"]]["hp"]; allPlayers[socket.id]["hp"] += hp; let toMutch = 0; if (allPlayers[socket.id]["hp"] > 100) { toMutch = allPlayers[socket.id]["hp"] - 100; } if (allPlayers[socket.id]["hp"] > 100) { allPlayers[socket.id]["hp"] = 100; } socket.emit("displayMsg", "Lebenspunkte +" + (hp - toMutch)); socket.emit("hpChange", allPlayers[socket.id]["hp"]); } else { allPlayers[socket.id]["slots"][slotArt] = itemName; socket.emit("addItemToInventar", itemName); } } io.sockets.emit("objAction", obj); } } player["action"] = true; }); }); function getNearEmptyField(x, y) { x = Math.round(x); y = Math.round(y); for (var j = 0; j < 20; j++) { for (var i = -1 - j; i < 2 + j; i++) { for (var k = -1; k < 2; k++) { //console.log("check", i, k, y + i, x + k) if (utilMap[y + i] && utilMap[y + i][x + k] == "" && cssMap[y + i] && cssMap[y + i][x + k] != "water") { return { y: y + i, x: x + k } } } } } } function calcDmgAndHitPlayer(player1, player2) { let dmg = 1; dmg += parseFloat(player1["slots"]["weapon"] ? itemAttrs[player1["slots"]["weapon"]]["dmg"] : 0); let armor = 1; for (var k in player2["slots"]) { if (k == "head" || k == "chest" || k == "legs") { armor += parseFloat(player1["slots"][k] ? itemAttrs[player1["slots"][k]]["armor"] : 0); } } let hitDmg = dmg * (armor / 100) * 100 player2["hp"] -= hitDmg; if (player2["hp"] < 0) { player2["hp"] = 0; } io.sockets.emit("newPlayerHp", { socketId: player2["socketId"], hp: player2["hp"] }) //console.log(hitDmg, dmg, armor, player1, player2) } function getRandomItem(minLvl, maxLvl) { //console.log("rnd", items.length, getRandomNumber(0, items.length), items) // return items[32] //Spaten // return items[32] //fish while (1) { let item = items[getRandomNumber(0, items.length)]; //console.log(item) if (item && (typeof (maxLvl) == "undefined" || typeof (minLvl) == "undefined" || (itemAttrs[item]["lvl"] >= minLvl && itemAttrs[item]["lvl"] <= maxLvl))) { return item; } } } function getNearestObject(x, y) { var mapX = Math.floor(x / 32); var mapY = Math.floor(y / 32); var obj = null; if (utilMap[mapY][mapX] != "") { obj = { mapX: mapX, mapY: mapY, name: utilMap[mapY][mapX] } } else { var rX = x % 32; var rY = y % 32; var sX = 0; var sY = 0; if (rX > 6 && rX < 26) { //He stands in the middle of the field (left-><-right) if (rY < 16) { //go Up sY = -1; } else { //go Down sY = 1; } } else if (rY > 6 && rY < 26) { //He stands in the middle of the field (up-><-down) if (rX < 16) { //go left sX = -1; } else { //go right sX = 1; } } if (utilMap[mapY + sY] && utilMap[mapY + sY][mapX + sX] != "") { obj = { mapY: mapY + sY, mapX: mapX + sX, name: utilMap[mapY + sY][mapX + sX] } } } return obj; } setInterval(function () { for (var id in allPlayers) { var player = allPlayers[id]; for (var key in player["keys"]) { if (player["keys"][key] && player["hp"] > 0) { //if key is pressed var tx = 0; var ty = 0; var mvnt = player["mvnt"]; if (key == 37) { //left tx = -1 * mvnt; } else if (key == 38) { //top ty = -1 * mvnt; } else if (key == 39) { //right tx = mvnt; } else if (key == 40) { //bottom ty = mvnt; } player.lookingLeft = tx > 0 ? -1 : (tx < 0 ? 1 : player.lookingLeft) player.lookingUp = ty > 0 ? -1 : (ty < 0 ? 1 : player.lookingUp) //console.log(player) if (!player["action"]) { var newX = player["x"] + tx; var newY = player["y"] + ty; var groundUnderPlayer = getGroundUnderPlayer(newX, newY); if (checkPlayerPosition(newX, newY, groundUnderPlayer, player)) { player["x"] = newX; player["y"] = newY; let mvnt = getPlayerMvnt(player, groundUnderPlayer); if (player["slots"]["boots"] && groundUnderPlayer != 0) { //Not water player["mvnt"] = mvnt + itemAttrs[player["slots"]["boots"]]["changeMovementLand"]; //console.log(groundUnderPlayer, player["mvnt"]) } else { player["mvnt"] = mvnt; } if (player["slots"]["item"] && itemAttrs[player["slots"]["item"]] && itemAttrs[player["slots"]["item"]]["changeMovementSpeed"]) { player["mvnt"] = mvnt + itemAttrs[player["slots"]["item"]]["changeMovementSpeed"]; } } } } } } io.sockets.emit("setpos", allPlayers); for (var id in allPlayers) { allPlayers[id]["special"] = {}; } }, 20); function checkPlayerPosition(newX, newY, groundUnderPlayer, player) { if (newX < 0 || newY < 0 || newX > maxX || newY > maxY) { return false; } if (player["mode"] == 0) { //ship if (groundUnderPlayer < 0 || groundUnderPlayer > 2) { //dont move with ship on land return false; } } else { if (groundUnderPlayer == 7) { //forrest so dont move return false; } } return true; } function getGroundUnderPlayer(newX, newY) { //0 = water; 10 = hard ground if (newX < 0 || newY < 0 || newX > maxX || newY > maxY) { return 0; } var mapX = Math.floor(newX / 32); var mapY = Math.floor(newY / 32); if (!cssMap[mapY] || !cssMap[mapY][mapX]) { return false; } var ground = cssMap[mapY][mapX]; var util = utilMap[mapY][mapX]; if (util == "forest") { return 7; } var groundSplit = ground.split("_"); if (groundSplit.length != 2) { if (ground == "water") { return 0; } return 10; //Ground } return parseFloat(groundSplit[1]); } function getPlayerMvnt(player, groundUnderPlayer) { if (player["mode"] == 0) { //ship if (groundUnderPlayer === 1) { return 0.5; } else if (groundUnderPlayer === 2) { return 0.1; } } else { if (groundUnderPlayer === 0) { return 0.1; } else if (groundUnderPlayer === 1) { return 0.5; } else if (groundUnderPlayer === 2) { return 0.8; } return 1.5; } return defaultMvnt; } function getRandomNumber(min, max) { //min (inclusive) and max (exclusive) return Math.floor(Math.random() * (max - min + 1)) + min; } function checkHitWithOtherPlayers(socketId) { let playersWithCollision = []; let mainPlayer = allPlayers[socketId]; for (var sid in allPlayers) { if (sid != socketId) { //Dont check collision with self let targetPlayer = allPlayers[sid]; let bottom = mainPlayer.keys["40"]; let left = mainPlayer.keys["37"]; //console.log(mainPlayer.x, mainPlayer.y, 28, targetPlayer.x, targetPlayer.y, 8) if (isCircleCircleCollision(mainPlayer.x, mainPlayer.y, 28, targetPlayer.x, targetPlayer.y, 8)) { let hit = false; //console.log(mainPlayer.lookingLeft, mainPlayer.lookingUp, mainPlayer.x, mainPlayer.y, targetPlayer.x, targetPlayer.y) if (mainPlayer.lookingLeft == 1 && mainPlayer.x >= targetPlayer.x) { hit = true; } else if (mainPlayer.lookingLeft == -1 && mainPlayer.x <= targetPlayer.x) { hit = true; } else if (mainPlayer.lookingUp == 1 && mainPlayer.y >= targetPlayer.y) { hit = true; } else if (mainPlayer.lookingUp == -1 && mainPlayer.y <= targetPlayer.y) { hit = true; } if (hit) { playersWithCollision.push(sid); } } } } return playersWithCollision; } function isCircleRecCollision(cx, cy, cr, rx, ry, rw, rh) { var cDistx = Math.abs(cx - rx); var cDisty = Math.abs(cy - ry); if (cDistx > rw / 2 + cr) return false; if (cDisty > rh / 2 + cr) return false; if (cDistx <= rw / 2) return true; if (cDisty <= rh / 2) return false; return (cDistx - rw / 2) * (cDistx - rw / 2) + (cDisty - rh / 2) * (cDisty - rh / 2) <= cr * cr; } function isCircleCircleCollision(x1, y1, r1, x2, y2, r2) { var dx = x1 - x2; var dy = y1 - y2; var sr = r1 + r2; if (Math.abs(dx) <= sr && Math.abs(dy) <= sr) { //Check main condition return Math.sqrt(dx * dx + dy * dy) < sr // true = collision detected! } return false; }