Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

maps.py configurable enter requirements #135

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
28 changes: 28 additions & 0 deletions design/maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,20 @@
[-1.54,105.6,126.56,56.96,"cave",2,0],
],
"instance":True,
"enter": {
# requirements to enter the dungeon
# TODO level, class,
#requires 1 cryptkey to enter
"items": {
"cryptkey": 1
},

# [mapKey, locationType, locationIndex, range]
"locations": [
# ["cave", "spawns", 2, 120], # spawn in front of door
["cave", "doors", 2, 120] # door at crypt castle
]
}
},
"goobrawl":{
"key":"jayson_GooIsland",
Expand Down Expand Up @@ -1151,6 +1165,20 @@
"drop_norm":4000,
"instance":True,
"lux":0.75,
"enter": {
# requirements to enter the dungeon
# TODO level, class,
"items": {
#requires 1 frozenkey to enter
"frozenkey": 1
},

# [mapKey, locationType, locationIndex, range]
"locations": [
# ["winterland", "spawns", 5, 120],
["winterland", "doors", 3, 120]
]
}
},
"winterland":{
#"key":"jayson_IceLandPrototype",
Expand Down
151 changes: 121 additions & 30 deletions node/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -5025,7 +5025,7 @@ function init_io() {
// if(data.place!="resort" && !G.maps[player.map].ref.transporter || simple_distance(G.maps[player.map].ref.transporter,player)>80) return socket.emit("game_response","transport_cant_reach");
// if(data.place=="resort" && player.map!="resort") return socket.emit("game_response","transport_cant_reach");
// }
server_log(data);
server_log(`${player.name} enter ${JSON.stringify(data)}`);
var name = randomStr(24);
if (data.place == "resort" && 0) {
var name = "resort_" + data.name;
Expand All @@ -5038,35 +5038,6 @@ function init_io() {
} else {
return fail_response("cant_enter");
}
} else if (data.place == "crypt" || data.place == "winter_instance") {
var f = "cave";
var ref = G.maps.cave.spawns[2];
var item = "cryptkey";
if (data.place == "winter_instance") {
f = "winterland";
ref = G.maps.winterland.spawns[5];
item = "frozenkey";
}
if (simple_distance(player, { in: f, map: f, x: ref[0], y: ref[1] }) > 120) {
return fail_response("transport_cant_reach");
}
if (data.name) {
// Player requested to enter an existing instance
if (instances[data.name] && instances[data.name].map == data.place) {
// The instance exists
transport_player_to(player, data.name);
} else {
// The instance doesn't exist
return fail_response("transport_cant_invalid");
}
} else {
if (!consume_one_by_id(player, item)) {
return fail_response("transport_cant_item");
}
instance = create_instance(name, data.place);
transport_player_to(player, name);
}
resend(player, "u+cid+reopen");
} else if (data.place == "dungeon0" && player.role == "gm") {
instance = create_instance(name, "dungeon0", { solo: player.id });
transport_player_to(player, name);
Expand Down Expand Up @@ -5171,6 +5142,126 @@ function init_io() {
instance.players[NPC_prefix + npc.id] = npc;
}
} else {
const gMap = data.place && G.maps[data.place];
if (gMap && gMap.instance) {
// Generic instance creation and transportation
// data.place is the name of the instance e.g bee_dungeon
// data.name is the id of the instance usually a number

const instanceExists = data.name && instances[data.name] && instances[data.name].map == data.place;

if (data.name) {
// Player requested to enter an existing instance
if (!instanceExists) {
// The instance doesn't exist
server_log(`${player.name} tried to enter ${data.place} (${data.name}) but it does not exist`);
return fail_response("transport_cant_invalid");
}
}

// Requirements for entering
if (gMap.enter) {
// Is there a place you need to be near to use the key
const validateRange = gMap.enter.locations && gMap.enter.locations.length > 0;
let inRange = !validateRange;

if (validateRange) {
server_log(`${data.place} ${player.name} ${gMap.enter.locations.length} locations to validate`);
for (const [locationsMapKey, locationType, locationIndex, range = 120] of gMap.enter.locations) {
if (!G.maps[locationsMapKey]) {
server_log(`${data.place} ${player.name} G.maps.${locationsMapKey} does not exist`);
continue;
}

if (!G.maps[locationsMapKey][locationType]) {
server_log(`${data.place} ${player.name} G.maps.${locationsMapKey}.${locationType} does not exist`);
continue;
}

if (!G.maps[locationsMapKey][locationType][locationIndex]) {
server_log(
`${data.place} ${player.name} G.maps.${locationsMapKey}.${locationType}.${locationIndex} does not exist`,
);
continue;
}

const location = G.maps[locationsMapKey][locationType][locationIndex];
const distanceToLocation = distance(player, {
in: locationsMapKey,
map: locationsMapKey,
x: location[0],
y: location[1],
});

server_log(
`${data.place} ${player.name} G.maps.${locationsMapKey}.${locationType}.${locationIndex} ${distanceToLocation} <= ${range}`,
);

if (distanceToLocation <= range) {
inRange = true;
break;
}
}
}

if (!inRange) {
return fail_response("transport_cant_reach");
}

// We check that the instance does not exist so the cost is not paid multiple times.
if (gMap.enter.items && !instanceExists) {
const itemsToConsume = [];

const quantityByItem = gMap.enter.items;

for (let i = 0; i < player.items.length; i++) {
const item = player.items[i];
if (item && quantityByItem[item.name]) {
server_log(`${data.place} ${player.name} has ${item.q || 1} x ${item.name} in slot ${i}`);

const quantity = Math.min(item.q || 1, quantityByItem[item.name]);

quantityByItem[item.name] -= quantity;
server_log(`${data.place} ${player.name} ${quantity} x ${item.name} to be removed`);
itemsToConsume.push([i, quantity]);

if (quantityByItem[item.name] == 0) {
delete quantityByItem[item.name];
}
}
}

// validate missing quantities
if (Object.keys(quantityByItem).length > 0) {
server_log(`${data.place} missing items ${JSON.stringify(quantityByItem)}`);
return fail_response("transport_cant_item", data.place, { items: quantityByItem });
}

for (const [inventory_index, quantity] of itemsToConsume) {
consume(player, inventory_index, quantity);
}
}
}

if (instanceExists) {
// transport to an existing instance
server_log(`${player.name} entering existing instance ${data.place} ${data.name}`);
// TODO: transport player to the spawn point the door maps too
transport_player_to(player, data.name);
} else {
// name is a random generated instance id
server_log(`${player.name} entering new instance ${data.place} ${name}`);
instance = create_instance(name, data.place);
// TODO: transport player to the spawn point the door maps too
transport_player_to(player, name);
}

resend(player, "u+cid+reopen");
success_response();
return;
}

server_log(`no handling for entering ${data.place}`);
return fail_response("transport_cant_reach");
}
success_response();
Expand Down