/******************************************************************************\ Handles clients changing nations. \******************************************************************************/ static void cm_affiliate(int client) { int nation, old, tile, ship; if ((nation = G_receive_nation(client)) < 0 || nation == g_clients[client].nation) return; old = g_clients[client].nation; /* Nation changing rules */ if (old == G_NN_PIRATE || (old != G_NN_NONE && nation != G_NN_PIRATE)) return; g_clients[client].nation = nation; /* If this client just joined a nation for the first time, try to give them a starter ship */ tile = -1; if (old == G_NN_NONE && (ship = G_ship_spawn(-1, client, -1, G_ST_SPIDER)) >= 0) { tile = g_ships[ship].tile; G_store_add(&g_ships[ship].store, G_CT_GOLD, 500); G_store_add(&g_ships[ship].store, G_CT_CREW, 25); G_store_add(&g_ships[ship].store, G_CT_RATIONS, 25); } N_broadcast("1112", G_SM_AFFILIATE, client, nation, tile); }
/******************************************************************************\ Client wants to do something to a tile via a ring command. \******************************************************************************/ static void cm_tile_ring(int client) { g_building_class_t *bc; i_ring_icon_t icon; int tile; tile = G_receive_tile(client); icon = (i_ring_icon_t)G_receive_range(client, 0, I_RING_ICONS); if (tile < 0 || icon < 0) return; /* Client wants to build a shipyard (tech preview) */ if (icon == I_RI_SHIPYARD) { bc = g_building_classes + G_BT_SHIPYARD; /* Can you do it? */ if (!G_pay(client, tile, &bc->cost, FALSE)) return; /* Pay for and build the town hall */ G_pay(client, tile, &bc->cost, TRUE); G_tile_build(tile, G_BT_SHIPYARD, g_clients[client].nation); return; } /* Client wants to buy a ship from their shipyard */ if (g_tiles[tile].building && g_tiles[tile].building->type == G_BT_SHIPYARD) { g_ship_type_t type; int ship; /* What ship do they want? */ if (icon == I_RI_SLOOP) type = G_ST_SLOOP; else if (icon == I_RI_SPIDER) type = G_ST_SPIDER; else if (icon == I_RI_GALLEON) type = G_ST_GALLEON; else return; /* Can they pay? */ if (!G_pay(client, tile, &g_ship_classes[type].cost, FALSE)) return; /* Pay for and spawn the ship. Don't pay if we couldn't spawn it for some reason! */ ship = G_ship_spawn(-1, client, tile, type); if (ship < 0) return; G_store_add(&g_ships[ship].store, G_CT_CREW, 10); G_store_add(&g_ships[ship].store, G_CT_RATIONS, 10); G_pay(client, tile, &g_ship_classes[type].cost, TRUE); return; } }
/******************************************************************************\ Add the values of [cost] to the store. \******************************************************************************/ void G_store_add_cost(g_store_t *store, const g_cost_t *cost) { int i; for (i = 0; i < G_CARGO_TYPES; i++) G_store_add(store, i, cost->cargo[i]); }
PyObject *Store_add(g_store_t *self , PyObject *args /*, PyObject *kwds */ ) { int cargo, amount, ret; if (!PyArg_ParseTuple(args, "ii", &cargo, &amount)) return NULL; ret = G_store_add(self, cargo, amount); return Py_BuildValue("i", ret); }
/******************************************************************************\ Determines whether a player can make a payment at a specific tile, returns TRUE if payment is possible. \******************************************************************************/ bool G_pay(n_client_id_t client, int tile, const g_cost_t *cost, bool pay) { g_cost_t unpaid; int i, j, neighbors[3]; if (!cost) return FALSE; unpaid = *cost; /* Just search neighboring ships until plots are implemented */ R_tile_neighbors(tile, neighbors); for (i = 0; i < 3; i++) { g_store_t *store; int ship; bool modified; ship = g_tiles[neighbors[i]].ship; if (!G_ship_controlled_by(ship, client) || g_ships[ship].rear_tile >= 0) continue; store = &g_ships[ship].store; /* Check what this ship can pay */ for (modified = FALSE, j = 0; j < G_CARGO_TYPES; j++) { int available; if ((available = store->cargo[j].amount) <= 0) continue; if (available > unpaid.cargo[j]) available = unpaid.cargo[j]; unpaid.cargo[j] -= available; /* Actually do the transfer */ if (pay) { G_store_add(store, j, -available); modified = TRUE; } } } /* See if everything has been paid for */ for (i = 0; i < G_CARGO_TYPES; i++) if (unpaid.cargo[i] > 0) return FALSE; return TRUE; }
/******************************************************************************\ Client wants to buy something. \******************************************************************************/ static void cm_ship_buy(int client) { g_store_t *buyer, *seller; int ship, trade_tile, trade_ship, cargo, amount, gold; if ((ship = G_receive_ship(client)) < 0 || (trade_tile = G_receive_tile(client)) < 0 || (cargo = G_receive_cargo(client)) < 0 || !G_ship_controlled_by(ship, client) || !G_ship_can_trade_with(ship, trade_tile)) return; trade_ship = g_tiles[trade_tile].ship; amount = N_receive_short(); buyer = &g_ships[ship].store; seller = &g_ships[trade_ship].store; amount = G_limit_purchase(buyer, seller, cargo, amount); if (amount == 0) return; /* Do the transfer. Cargo must be subtracted before it is added or it could overflow and get clamped! */ if (amount > 0) { gold = seller->cargo[cargo].sell_price * amount; G_store_add(buyer, G_CT_GOLD, -gold); G_store_add(seller, cargo, -amount); G_store_add(seller, G_CT_GOLD, gold); G_store_add(buyer, cargo, amount); } else { amount = -amount; gold = seller->cargo[cargo].buy_price * amount; G_store_add(seller, G_CT_GOLD, -gold); G_store_add(buyer, cargo, -amount); G_store_add(buyer, G_CT_GOLD, gold); G_store_add(seller, cargo, amount); } }