winning/losing page
This commit is contained in:
+16
-56
@@ -7,7 +7,7 @@
|
||||
* MY_CONSTANT
|
||||
* */
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
//#include <math.h>
|
||||
#include "base/impl.c"
|
||||
#include "lib/network.c"
|
||||
#include "render.c"
|
||||
@@ -101,6 +101,7 @@ typedef struct TransactionResult {
|
||||
|
||||
typedef struct ParsedServerMessage {
|
||||
Message type;
|
||||
u8 byte;
|
||||
u16 port;
|
||||
u16 port2;
|
||||
u32 ip;
|
||||
@@ -323,51 +324,6 @@ fn void renderPercentBar(TuiState* tui, u16 x, u16 y, u16 width, u8 ansi_color,
|
||||
}
|
||||
}
|
||||
|
||||
fn void renderSpeechBubble(TuiState* tui, u16 x, u16 y, u16 max_width, String message, SpeechTailDirection dir) {
|
||||
Pixel* buf = tui->frame_buffer;
|
||||
Dim2 screen_dimensions = tui->screen_dimensions;
|
||||
// calculate dimenions
|
||||
u32 height = (message.length / max_width) + 1;
|
||||
u32 width = message.length;
|
||||
if (message.length > max_width) {
|
||||
width = max_width;
|
||||
}
|
||||
if (width < 12) {
|
||||
width = 12; // minimum width
|
||||
}
|
||||
|
||||
// print the upper border
|
||||
renderUtf8CharToBuffer(buf, x, y, "╭", screen_dimensions);
|
||||
for (i32 i = 0; i < width+1; i++) {
|
||||
renderUtf8CharToBuffer(buf, x+1+i, y, "─", screen_dimensions);
|
||||
}
|
||||
renderUtf8CharToBuffer(buf, x+width+1, y, "╮", screen_dimensions);
|
||||
|
||||
// start printing the rows
|
||||
for (u32 i = 0; i < height; i++) {
|
||||
renderUtf8CharToBuffer(buf, x, y+1+i, "│", screen_dimensions);
|
||||
// print the line of text
|
||||
for (u32 j = 0; j < width; j++) {
|
||||
u32 character_index = (i*(width-1))+j;
|
||||
u16 pos = (x+1+j) + (screen_dimensions.width * (y+1+i));
|
||||
if (message.length > character_index) {
|
||||
buf[pos].bytes[0] = message.bytes[character_index];
|
||||
} else {
|
||||
buf[pos].bytes[0] = ' ';
|
||||
}
|
||||
}
|
||||
renderUtf8CharToBuffer(buf, x+1+width, y+1+i, "│", screen_dimensions);
|
||||
}
|
||||
|
||||
// print the bottom box border
|
||||
renderUtf8CharToBuffer(buf, x, y+1+height, "╰", screen_dimensions);
|
||||
for (i32 i = 0; i < width+1; i++) {
|
||||
renderUtf8CharToBuffer(buf, x+1+i, y+1+height, "─", screen_dimensions);
|
||||
}
|
||||
renderUtf8CharToBuffer(buf, x+width+1, y+1+height, "╯", screen_dimensions);
|
||||
// TODO actually print the speech tail
|
||||
}
|
||||
|
||||
fn void renderStaticAssetToPixelBuffer(TuiState* tui, u8* asset, u32 len, u16 x, u16 y) {
|
||||
u16 line = 0;
|
||||
u16 x_in_line = 0;
|
||||
@@ -431,6 +387,9 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
|
||||
case MessageTurnTick:
|
||||
case MessageNewAccountCreated:
|
||||
case MessageBadPw: {/*nothing to parse but the type*/} break;
|
||||
case MessageGameOver: {
|
||||
parsed.byte = message[msg_pos++];
|
||||
} break;
|
||||
case MessageTransactionResult: {
|
||||
parsed.tx_result.buying = message[msg_pos++];
|
||||
parsed.tx_result.qty = readU32FromBufferLE(message + msg_pos);
|
||||
@@ -551,6 +510,11 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
||||
while (next_net_msg != NULL) {
|
||||
msg_iters += 0;
|
||||
switch (msg.type) {
|
||||
case MessageGameOver: {
|
||||
state->screen = state->me.id == msg.byte ? ScreenVictory : ScreenDefeat;
|
||||
sprintf(sbuf,"got winner id: %d", msg.byte);
|
||||
addSystemMessage((u8*)sbuf);
|
||||
} break;
|
||||
case MessagePayoffResult: {
|
||||
state->ship_tab_states = ShipTabStateMain;
|
||||
} break;
|
||||
@@ -732,10 +696,8 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
||||
u32 principal_borrowed = selected_ship_cost - STARTING_DOWN_PAYMENT;
|
||||
f32 mortgage_rate = calcInterestRate(selected_ship_cost, STARTING_DOWN_PAYMENT);
|
||||
f32 r = mortgage_rate / 100.0;
|
||||
f32 rm = r / 12.0;
|
||||
u32 n = 12 * 4;
|
||||
u32 payment = principal_borrowed * (rm*pow((1.0+rm),n))/(pow((1+rm),n) - 1);
|
||||
sprintf(sbuf, "Mortgage: $%d @ %f%% = $%d minimum payment per turn", selected_ship_cost - STARTING_DOWN_PAYMENT, mortgage_rate, payment);
|
||||
u32 payment = principal_borrowed * r;
|
||||
sprintf(sbuf, "Mortgage: $%d @ %f%% = $%d interest after first turn", selected_ship_cost - STARTING_DOWN_PAYMENT, mortgage_rate, payment);
|
||||
renderStrToBuffer(tui->frame_buffer, 5, ++line, sbuf, screen_dimensions);
|
||||
line++;
|
||||
// the table
|
||||
@@ -1359,23 +1321,21 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
||||
case ScreenVictory: {
|
||||
// SIMULATION
|
||||
if (user_pressed_esc || input_buffer[0] == ASCII_RETURN || input_buffer[0] == ASCII_LINE_FEED) {
|
||||
state->screen = ScreenMainGame;
|
||||
should_quit = true;
|
||||
}
|
||||
|
||||
// RENDERING
|
||||
renderStrToBuffer(tui->frame_buffer, 10, 10, "You WIN!!!", screen_dimensions);
|
||||
renderStrToBuffer(tui->frame_buffer, 5, 11, "You paid off your ships mortgage and are a free trader!", screen_dimensions);
|
||||
} break;
|
||||
case ScreenDefeat: {
|
||||
// SIMULATION
|
||||
if (user_pressed_esc || input_buffer[0] == ASCII_RETURN || input_buffer[0] == ASCII_LINE_FEED) {
|
||||
state->me.id = 0;
|
||||
state->menu.selected_index = 0;
|
||||
clearServerSentState();
|
||||
state->screen = ScreenCreateCharacter;
|
||||
should_quit = true;
|
||||
}
|
||||
|
||||
// RENDERING
|
||||
renderStrToBuffer(tui->frame_buffer, 10, 10, "You died...", screen_dimensions);
|
||||
renderStrToBuffer(tui->frame_buffer, 10, 10, "You lose, forever doomed to work for the bank...", screen_dimensions);
|
||||
renderStrToBuffer(tui->frame_buffer, 10, 11, "[press ESC to continue]", screen_dimensions);
|
||||
} break;
|
||||
case Screen_Count:
|
||||
|
||||
+30
-173
@@ -59,17 +59,6 @@ typedef struct ParsedClientCommandThreadQueue {
|
||||
Cond not_full;
|
||||
} ParsedClientCommandThreadQueue;
|
||||
|
||||
typedef struct Entity {
|
||||
bool changed;
|
||||
u8 x;
|
||||
u8 y;
|
||||
u8 color;
|
||||
EntityType type;
|
||||
u32 misc;
|
||||
u64 id;
|
||||
u64 features;
|
||||
} Entity;
|
||||
|
||||
typedef struct Account {
|
||||
u8 destination_sys_idx;
|
||||
bool changed;
|
||||
@@ -79,26 +68,6 @@ typedef struct Account {
|
||||
PlayerShip ship;
|
||||
} Account;
|
||||
|
||||
typedef struct EntityList {
|
||||
u64 length; // the currently used length
|
||||
u64 capacity;
|
||||
Entity* items;
|
||||
} EntityList;
|
||||
|
||||
typedef struct EntityChunk {
|
||||
u64 length; // the currently used # of entities in this chunk
|
||||
u64 capacity; // the "chunk size" / space in this chunk
|
||||
struct EntityChunk* next; // the next chunk
|
||||
Entity* items; // the actual entities
|
||||
} EntityChunk;
|
||||
|
||||
typedef struct ChunkedEntityList {
|
||||
u64 length; // the current number of entities
|
||||
u64 chunk_size; // the # of entities per chunk
|
||||
u64 chunks; // the # of chunks in this list so far
|
||||
EntityChunk* first; // the first chunk of entities
|
||||
} ChunkedEntityList;
|
||||
|
||||
typedef struct Client {
|
||||
u16 lan_port;
|
||||
i32 lan_ip;
|
||||
@@ -134,9 +103,7 @@ typedef struct State {
|
||||
///// Global Variables
|
||||
global State state = { 0 };
|
||||
global Arena permanent_arena = { 0 };
|
||||
global const Entity NULL_ENTITY = { 0 };
|
||||
global bool debug_mode = false;
|
||||
global ChunkedEntityList free_chunks = { 0, CHUNK_SIZE, 0, NULL };
|
||||
|
||||
///// functionImplementations()
|
||||
fn ParsedClientCommandThreadQueue* newPCCThreadQueue(Arena* a) {
|
||||
@@ -182,44 +149,6 @@ fn ParsedClientCommand* pccThreadSafeNonblockingQueuePop(ParsedClientCommandThre
|
||||
return result;
|
||||
}
|
||||
|
||||
fn u64 entitySerialize(Entity current, Account* acct, u64 index, u8 bytes[]) {
|
||||
// send entity header (common to all entity types)
|
||||
index += writeU64ToBufferLE(bytes + index, current.id);
|
||||
index += writeU64ToBufferLE(bytes + index, current.features);
|
||||
bytes[index++] = current.x;
|
||||
bytes[index++] = current.y;
|
||||
bytes[index++] = (u8)current.type; // EntityType
|
||||
|
||||
//if (CheckFlag(current.features, FeatureRegensHp)) {
|
||||
// index += writeU16ToBufferLE(bytes + index, current.hp);
|
||||
// index += writeU16ToBufferLE(bytes + index, current.max_hp);
|
||||
//}
|
||||
|
||||
// send character-specific details (color and name)
|
||||
if (current.type == EntityCharacter) {
|
||||
bytes[index++] = current.color;
|
||||
// send name string
|
||||
index += writeU64ToBufferLE(bytes + index, acct->name.length);
|
||||
for (u32 j = 0; j < acct->name.length; j++) {
|
||||
bytes[index++] = acct->name.bytes[j];
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
fn u64 entityFeaturesFromType(EntityType type) {
|
||||
u64 result = 0;
|
||||
switch (type) {
|
||||
case EntityCharacter: {
|
||||
SetFlag(result, FeatureWalksAround);
|
||||
SetFlag(result, FeatureCanFight);
|
||||
} break;
|
||||
default: {
|
||||
} break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn Account* findAccountByName(String name) {
|
||||
for (u32 i = 0; i < ACCOUNT_LEN; i++) {
|
||||
if (stringsEq(&state.accounts[i].name, &name)) {
|
||||
@@ -229,93 +158,6 @@ fn Account* findAccountByName(String name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fn u64 pushEntity(EntityChunk* chunk, Entity e) {
|
||||
assert(chunk->length < chunk->capacity);
|
||||
chunk->items[chunk->length] = e;
|
||||
u64 result = chunk->length;
|
||||
chunk->length += 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
fn bool isSpaceInChunk(EntityChunk* chunk) {
|
||||
return chunk->length < chunk->capacity;
|
||||
}
|
||||
|
||||
fn bool allChunksFull(ChunkedEntityList list) {
|
||||
return list.length >= (list.chunk_size * list.chunks);
|
||||
}
|
||||
|
||||
fn EntityChunk* pushNewChunk(Arena* a, ChunkedEntityList* list) {
|
||||
EntityChunk* new_chunk;
|
||||
if (free_chunks.length > 0) {
|
||||
new_chunk = free_chunks.first;
|
||||
free_chunks.length -= 1;
|
||||
free_chunks.first = new_chunk->next;
|
||||
} else {
|
||||
new_chunk = arenaAlloc(a, sizeof(EntityChunk));
|
||||
// alloc the new chunk of entities
|
||||
new_chunk->length = 0;
|
||||
new_chunk->capacity = list->chunk_size;
|
||||
new_chunk->next = NULL;
|
||||
new_chunk->items = arenaAllocArray(a, Entity, list->chunk_size);
|
||||
}
|
||||
// bookeeping in the list
|
||||
list->chunks += 1;
|
||||
if (list->first == NULL) {
|
||||
list->first = new_chunk;
|
||||
} else {
|
||||
EntityChunk* last = list->first;
|
||||
while (last->next != NULL) {
|
||||
last = last->next;
|
||||
}
|
||||
last->next = new_chunk;
|
||||
}
|
||||
return new_chunk;
|
||||
}
|
||||
|
||||
fn Entity* entityPtrFromChunkList(ChunkedEntityList* list, i32 index) {
|
||||
Entity* result = (Entity*)&NULL_ENTITY;
|
||||
i32 chunk_index = index / list->chunk_size;
|
||||
EntityChunk* chunk = list->first;
|
||||
for (i32 i = 0; i < chunk_index; i++) {
|
||||
chunk = chunk->next;
|
||||
}
|
||||
result = &chunk->items[index % list->chunk_size];
|
||||
return result;
|
||||
}
|
||||
|
||||
fn Entity entityFromChunkList(ChunkedEntityList* list, i32 index) {
|
||||
Entity result = {0};
|
||||
i32 chunk_index = index / list->chunk_size;
|
||||
EntityChunk* chunk = list->first;
|
||||
for (i32 i = 0; i < chunk_index; i++) {
|
||||
chunk = chunk->next;
|
||||
}
|
||||
result = chunk->items[index % list->chunk_size];
|
||||
return result;
|
||||
}
|
||||
|
||||
fn bool deleteLastEntity(ChunkedEntityList* list, EntityChunk* last_chunk, EntityChunk* second_to_last_chunk) {
|
||||
last_chunk->length -= 1;
|
||||
list->length -= 1;
|
||||
// don't delete the room's only chunk, but otherwise move the chunk to the free-list
|
||||
if (last_chunk->length == 0 && last_chunk != list->first) {
|
||||
list->chunks -= 1;
|
||||
second_to_last_chunk->next = NULL;
|
||||
free_chunks.length += 1;
|
||||
EntityChunk* last_free_chunk = free_chunks.first;
|
||||
if (last_free_chunk) {
|
||||
while (last_free_chunk->next != NULL) {
|
||||
last_free_chunk = last_free_chunk->next;
|
||||
}
|
||||
last_free_chunk->next = last_chunk;
|
||||
} else {
|
||||
free_chunks.first = last_chunk;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn void exitWithErrorMessage(ptr msg) {
|
||||
printf("error: %s", msg);
|
||||
exit(1);
|
||||
@@ -515,8 +357,7 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
|
||||
|
||||
printf("Logging in player: %s %d %s\n", MESSAGE_STRINGS[parsed.type], name_len, message + 7);
|
||||
} break;
|
||||
case CommandKeepAlive:
|
||||
break;
|
||||
case CommandKeepAlive: break;
|
||||
case CommandPayMortgage: {
|
||||
parsed.id = readU64FromBufferLE(message + msg_idx);
|
||||
printf("paying off %lld\n", parsed.id);
|
||||
@@ -720,8 +561,10 @@ fn void* gameLoop(void* params) {
|
||||
u32 qty_traded = 0;
|
||||
u32 credit_value = 0;
|
||||
if (is_buying_from_system) {
|
||||
u32 ship_space = MAX_u32;
|
||||
if (COMMODITIES[msg.commodity].unit == StorageUnitContainer) {
|
||||
u32 ship_space = account->ship.cu_m_fuel - account->ship.commodities[CommodityHydrogenFuel];
|
||||
if (msg.commodity == CommodityOxygen) {
|
||||
ship_space = account->ship.cu_m_o2 - account->ship.commodities[CommodityOxygen];
|
||||
} else if (COMMODITIES[msg.commodity].unit == StorageUnitContainer) {
|
||||
ship_space = account->ship.vacuum_cargo_slots - usedVacuumCargoSlots(account->ship);
|
||||
}
|
||||
for (u32 amount_to_buy = Min(msg.qty, total_available); amount_to_buy > 0; amount_to_buy--, total_available--, ship_space--) {
|
||||
@@ -858,12 +701,12 @@ fn void* gameLoop(void* params) {
|
||||
.remaining_mortgage = template.base_cost - STARTING_DOWN_PAYMENT,
|
||||
.interest_rate = calcInterestRate(template.base_cost, STARTING_DOWN_PAYMENT),
|
||||
.credits = 10000.0,
|
||||
//.cu_m_fuel; // we are just saying you can buy as much fuel as you want
|
||||
//.cu_m_o2; // we are just saying you can buy as much o2 as you want
|
||||
.cu_m_fuel = template.cu_m_fuel,
|
||||
.cu_m_o2 = template.cu_m_o2,
|
||||
.id = account->id,
|
||||
};
|
||||
player_ship.commodities[CommodityHydrogenFuel] = 2000;
|
||||
player_ship.commodities[CommodityOxygen] = 1000;
|
||||
player_ship.commodities[CommodityHydrogenFuel] = player_ship.cu_m_fuel;
|
||||
player_ship.commodities[CommodityOxygen] = player_ship.cu_m_o2;
|
||||
account->ship = player_ship;
|
||||
printf("ship_type=%s, client_handle=%d, acct_id=%d\n", SHIP_TYPE_STRINGS[msg.byte], client_handle, account->id);
|
||||
u32 starting_system_idx = rand() % STAR_SYSTEM_COUNT;
|
||||
@@ -933,12 +776,15 @@ fn void* gameLoop(void* params) {
|
||||
outgoingMessageQueuePush(state.network_send_queue, &outgoing_message);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} unlockMutex(&state.mutex); unlockMutex(&state.client_mutex);
|
||||
}
|
||||
|
||||
if (state.someone_won) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LaneSync();
|
||||
|
||||
u32 player_count = 0;
|
||||
@@ -990,22 +836,30 @@ fn void* gameLoop(void* params) {
|
||||
acct->ship.ready_to_depart = false;
|
||||
acct->changed = true;
|
||||
|
||||
// look for a winner + increase the mortgage from interest
|
||||
// increase the mortgage from interest
|
||||
if (!shipIsNull(&acct->ship)) {
|
||||
if (acct->ship.remaining_mortgage > 0) {
|
||||
acct->ship.remaining_mortgage += acct->ship.remaining_mortgage * (acct->ship.interest_rate / 100.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// look for a winner
|
||||
Range1u64 ship_range = LaneRange(player_count);
|
||||
for (u32 i = ship_range.min; i < ship_range.max; i++) {
|
||||
Account* acct = &state.accounts[i];
|
||||
if (!shipIsNull(&acct->ship)) {
|
||||
if (acct->ship.remaining_mortgage == 0) {
|
||||
state.winner_id = acct->id;
|
||||
state.someone_won = true;
|
||||
printf("someone WON!!! %d\n", i);
|
||||
acct->changed = true;
|
||||
break;
|
||||
} else {
|
||||
acct->ship.remaining_mortgage += acct->ship.remaining_mortgage * (acct->ship.interest_rate / 100.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO pay the mortgage payment
|
||||
}
|
||||
|
||||
// 3. scratch cleanup
|
||||
arenaClear(&scratch_arena);
|
||||
|
||||
@@ -1209,6 +1063,9 @@ i32 main(i32 argc, ptr argv[]) {
|
||||
osThreadJoin(game_threads[i], MAX_u64);
|
||||
}
|
||||
|
||||
osThreadJoin(recv_thread, MAX_u64);
|
||||
osThreadJoin(send_thread, MAX_u64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+20
-14
@@ -6,7 +6,7 @@
|
||||
|
||||
///// #define some game-tunable constants
|
||||
#define STARTING_DOWN_PAYMENT (10000)
|
||||
#define SHIP_DETAIL_COUNT (8)
|
||||
#define SHIP_DETAIL_COUNT (7)
|
||||
#define STAR_SYSTEM_COUNT (40)
|
||||
#define MAP_WIDTH (36)
|
||||
#define MAP_HEIGHT (12)
|
||||
@@ -34,14 +34,14 @@ typedef enum ShipType {
|
||||
ShipSparrow,
|
||||
ShipDart,
|
||||
ShipHaulerPrimeZ1,
|
||||
ShipNX400,
|
||||
// ShipNX400,
|
||||
ShipType_Count,
|
||||
} ShipType;
|
||||
global str SHIP_TYPE_STRINGS[] = {
|
||||
"Sparrow",
|
||||
"Dart",
|
||||
"Hauler-Prime Z-1",
|
||||
"NX-400",
|
||||
// "NX-400",
|
||||
};
|
||||
|
||||
typedef struct ShipTemplate {
|
||||
@@ -54,33 +54,39 @@ typedef struct ShipTemplate {
|
||||
u16 passenger_amenities_flags;
|
||||
u16 smugglers_hold_cu_m;
|
||||
u32 base_cost;
|
||||
u32 cu_m_fuel;
|
||||
u32 cu_m_o2;
|
||||
} ShipTemplate;
|
||||
|
||||
global ShipTemplate SHIPS[] = {
|
||||
{
|
||||
.type = ShipSparrow, .drive_efficiency = 1, .life_support_efficiency = 2,
|
||||
.type = ShipSparrow, .drive_efficiency = 10, .life_support_efficiency = 2,
|
||||
.vacuum_cargo_slots = 5, .climate_cargo_slots = 0, .passenger_berths = 0,
|
||||
.passenger_amenities_flags = 0,
|
||||
.smugglers_hold_cu_m = 1, .base_cost = 100000,
|
||||
.cu_m_fuel = 2000, .cu_m_o2 = 1000,
|
||||
},
|
||||
{
|
||||
.type = ShipDart, .drive_efficiency = 12, .life_support_efficiency = 4,
|
||||
.vacuum_cargo_slots = 9, .climate_cargo_slots = 1, .passenger_berths = 1,
|
||||
.type = ShipDart, .drive_efficiency = 70, .life_support_efficiency = 4,
|
||||
.vacuum_cargo_slots = 10, .climate_cargo_slots = 1, .passenger_berths = 1,
|
||||
.passenger_amenities_flags = 0,
|
||||
.smugglers_hold_cu_m = 0, .base_cost = 150000,
|
||||
.cu_m_fuel = 2000, .cu_m_o2 = 1000,
|
||||
},
|
||||
{
|
||||
.type = ShipHaulerPrimeZ1, .drive_efficiency = 3, .life_support_efficiency = 3,
|
||||
.vacuum_cargo_slots = 25, .climate_cargo_slots = 5, .passenger_berths = 0,
|
||||
.type = ShipHaulerPrimeZ1, .drive_efficiency = 50, .life_support_efficiency = 3,
|
||||
.vacuum_cargo_slots = 100, .climate_cargo_slots = 5, .passenger_berths = 0,
|
||||
.passenger_amenities_flags = 0,
|
||||
.smugglers_hold_cu_m = 0, .base_cost = 250000,
|
||||
.cu_m_fuel = 2000, .cu_m_o2 = 1000,
|
||||
},
|
||||
{
|
||||
/* {
|
||||
.type = ShipNX400, .drive_efficiency = 6, .life_support_efficiency = 8,
|
||||
.vacuum_cargo_slots = 5, .climate_cargo_slots = 5, .passenger_berths = 5,
|
||||
.passenger_amenities_flags = 0,
|
||||
.smugglers_hold_cu_m = 0, .base_cost = 350000,
|
||||
},
|
||||
.cu_m_fuel = 2000, .cu_m_o2 = 1000,
|
||||
},*/
|
||||
};
|
||||
|
||||
fn f32 calcInterestRate(u32 cost, u32 down_payment) {
|
||||
@@ -93,10 +99,10 @@ global FieldDescriptor SHIP_FIELDS[SHIP_DETAIL_COUNT] = {
|
||||
{ "Cost", FieldTypeU32, offsetof(ShipTemplate, base_cost), 8 },
|
||||
{ "DriveEff", FieldTypeU8, offsetof(ShipTemplate, drive_efficiency), 8 },
|
||||
{ "LifeSupp", FieldTypeU8, offsetof(ShipTemplate, life_support_efficiency), 8 },
|
||||
{ "V.Cargo", FieldTypeU16, offsetof(ShipTemplate, vacuum_cargo_slots), 7 },
|
||||
{ "C.Cargo", FieldTypeU16, offsetof(ShipTemplate, climate_cargo_slots), 7 },
|
||||
{ "Passengers", FieldTypeU16, offsetof(ShipTemplate, passenger_berths), 10 },
|
||||
{ "SmugglersHold", FieldTypeU16, offsetof(ShipTemplate, smugglers_hold_cu_m), 13 },
|
||||
{ "Cargo", FieldTypeU16, offsetof(ShipTemplate, vacuum_cargo_slots), 7 },
|
||||
{ "FuelTank", FieldTypeU32, offsetof(ShipTemplate, cu_m_fuel), 8 },
|
||||
{ "O2 Tank", FieldTypeU32, offsetof(ShipTemplate, cu_m_o2), 8 },
|
||||
// { "SmugglersHold", FieldTypeU16, offsetof(ShipTemplate, smugglers_hold_cu_m), 13 },
|
||||
};
|
||||
|
||||
typedef enum EquipmentType {
|
||||
|
||||
Reference in New Issue
Block a user