static void NET_SV_SendWaitingData(net_client_t *client) { net_waitdata_t wait_data; net_packet_t *packet; net_client_t *controller; int i; NET_SV_AssignPlayers(); controller = NET_SV_Controller(); wait_data.num_players = NET_SV_NumPlayers(); wait_data.num_drones = NET_SV_NumDrones(); wait_data.ready_players = NET_SV_NumReadyPlayers(); wait_data.max_players = NET_SV_MaxPlayers(); wait_data.is_controller = (client == controller); wait_data.consoleplayer = client->player_number; // Send the WAD and dehacked checksums of the controlling client. // If no controller found (?), send the details that the client // is expecting anyway. if (controller == NULL) { controller = client; } memcpy(&wait_data.wad_sha1sum, &controller->wad_sha1sum, sizeof(sha1_digest_t)); memcpy(&wait_data.deh_sha1sum, &controller->deh_sha1sum, sizeof(sha1_digest_t)); wait_data.is_freedoom = controller->is_freedoom; // set name and address of each player: for (i = 0; i < wait_data.num_players; ++i) { M_StringCopy(wait_data.player_names[i], sv_players[i]->name, MAXPLAYERNAME); M_StringCopy(wait_data.player_addrs[i], NET_AddrToString(sv_players[i]->addr), MAXPLAYERNAME); } // Construct packet: packet = NET_NewPacket(10); NET_WriteInt16(packet, NET_PACKET_TYPE_WAITING_DATA); NET_WriteWaitData(packet, &wait_data); // Send packet to client and free NET_Conn_SendPacket(&client->connection, packet); NET_FreePacket(packet); }
// // Read the header for a savegame // dboolean P_ReadSaveGameHeader(char *description) { byte a, b, c; char vcheck[VERSIONSIZE]; char read_vcheck[VERSIONSIZE]; for (int i = 0; i < SAVESTRINGSIZE; i++) description[i] = saveg_read8(); for (int i = 0; i < VERSIONSIZE; i++) read_vcheck[i] = saveg_read8(); memset(vcheck, 0, sizeof(vcheck)); strcpy(vcheck, PACKAGE_SAVEGAMEVERSIONSTRING); if (strcmp(read_vcheck, vcheck)) { menuactive = false; C_ShowConsole(); C_Warning("This savegame requires <i>%s</i>.", read_vcheck); return false; // bad version } gameskill = (skill_t)saveg_read8(); gameepisode = saveg_read8(); gamemap = saveg_read8(); if (gamemode != commercial) { if (gamemap == 10) { gamemap = 4; M_StringCopy(speciallumpname, "E1M4B", 6); } else if (gamemap == 11) { gamemap = 8; M_StringCopy(speciallumpname, "E1M8B", 6); } } saveg_read8(); // get the times a = saveg_read8(); b = saveg_read8(); c = saveg_read8(); leveltime = (a << 16) + (b << 8) + c; return true; }
static void TXT_KeyInputDrawer(TXT_UNCAST_ARG(key_input)) { TXT_CAST_ARG(txt_key_input_t, key_input); char buf[20]; int i; if (*key_input->variable == 0) { M_StringCopy(buf, "(none)", sizeof(buf)); } else { TXT_GetKeyDescription(*key_input->variable, buf, sizeof(buf)); } TXT_SetWidgetBG(key_input); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(buf); for (i=strlen(buf); i<KEY_INPUT_WIDTH; ++i) { TXT_DrawString(" "); } }
boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping, void *structptr, char *name, char *value) { deh_mapping_entry_t *entry; void *location; entry = GetMappingEntryByName(context, mapping, name); if (entry == NULL) { return false; } // Sanity check: if (!entry->is_string) { DEH_Error(context, "Tried to set '%s' as string (BUG)", name); return false; } location = GetStructField(structptr, mapping, entry); // Copy value into field: M_StringCopy(location, value, entry->size); return true; }
static void PlayerQuitGame(player_t *player) { static char exitmsg[80]; unsigned int player_num; player_num = player - players; // Note: // The Heretic source code does this, which doesn't actually work. // As a result, the exit message is never seen. M_StringCopy(exitmsg, "PLAYER 1 LEFT THE GAME", sizeof(exitmsg)); exitmsg[7] += player_num; players[consoleplayer].message = exitmsg; playeringame[player_num] = false; players[consoleplayer].message = exitmsg; // TODO: check if it is sensible to do this: if (demorecording) { G_CheckDemoStatus (); } }
static char *GetFullExePath(const char *program) { char *result; char *sep; size_t result_len; unsigned int path_len; sep = strrchr(myargv[0], DIR_SEPARATOR); if (sep == NULL) { result = strdup(program); } else { path_len = sep - myargv[0] + 1; result_len = strlen(program) + path_len + 1; result = malloc(result_len); M_StringCopy(result, myargv[0], result_len); result[path_len] = '\0'; M_StringConcat(result, program, result_len); } return result; }
static void TXT_JoystickInputDrawer(TXT_UNCAST_ARG(joystick_input)) { TXT_CAST_ARG(txt_joystick_input_t, joystick_input); char buf[20]; int i; if (*joystick_input->variable < 0) { M_StringCopy(buf, "(none)", sizeof(buf)); } else { GetJoystickButtonDescription(*joystick_input->variable, buf, sizeof(buf)); } TXT_SetWidgetBG(joystick_input); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(buf); for (i=strlen(buf); i<JOYSTICK_INPUT_WIDTH; ++i) { TXT_DrawString(" "); } }
static void PlayerQuitGame(player_t *player) { static char exitmsg[80]; unsigned int player_num; player_num = player - players; // Do this the same way as Vanilla Doom does, to allow dehacked // replacements of this message M_StringCopy(exitmsg, DEH_String("Player 1 left the game"), sizeof(exitmsg)); exitmsg[7] += player_num; playeringame[player_num] = false; players[consoleplayer].message = exitmsg; // [crispy] don't interpolate players who left the game player->mo->interp = false; // TODO: check if it is sensible to do this: if (demorecording) { G_CheckDemoStatus (); } }
static void TXT_MouseInputDrawer(TXT_UNCAST_ARG(mouse_input)) { TXT_CAST_ARG(txt_mouse_input_t, mouse_input); char buf[20]; int i; if (*mouse_input->variable < 0) { M_StringCopy(buf, "(none)", sizeof(buf)); } else { GetMouseButtonDescription(*mouse_input->variable, buf, sizeof(buf)); } TXT_SetWidgetBG(mouse_input); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(buf); for (i=strlen(buf); i<MOUSE_INPUT_WIDTH; ++i) { TXT_DrawString(" "); } }
char *M_StringReplace(const char *haystack, const char *needle, const char *replacement) { char *result, *dst; const char *p; size_t needle_len = strlen(needle); size_t result_len, dst_len; // Iterate through occurrences of 'needle' and calculate the size of // the new string. result_len = strlen(haystack) + 1; p = haystack; for (;;) { p = strstr(p, needle); if (p == NULL) { break; } p += needle_len; result_len += strlen(replacement) - needle_len; } // Construct new string. result = malloc(result_len); if (result == NULL) { I_Error("M_StringReplace: Failed to allocate new string"); return NULL; } dst = result; dst_len = result_len; p = haystack; while (*p != '\0') { if (!strncmp(p, needle, needle_len)) { M_StringCopy(dst, replacement, dst_len); p += needle_len; dst += strlen(replacement); dst_len -= strlen(replacement); } else { *dst = *p; ++dst; --dst_len; ++p; } } *dst = '\0'; return result; }
static void GetMouseButtonDescription(int button, char *buf, size_t buf_len) { switch (button) { case 0: M_StringCopy(buf, "LEFT", buf_len); break; case 1: M_StringCopy(buf, "RIGHT", buf_len); break; case 2: M_StringCopy(buf, "MID", buf_len); break; default: snprintf(buf, buf_len, "BUTTON #%i", button + 1); break; } }
boolean M_StringConcat(char *dest, const char *src, size_t dest_size) { size_t offset; offset = strlen(dest); if (offset > dest_size) { offset = dest_size; } return M_StringCopy(dest + offset, src, dest_size - offset); }
static boolean SCSaveGame(int option) { #ifdef USE_VIRTUALKEYBOARD int hour, minute, second; #endif char *ptr; if (!FileMenuKeySteal) { FileMenuKeySteal = true; M_StringCopy(oldSlotText, SlotText[option], sizeof(oldSlotText)); #ifdef USE_VIRTUALKEYBOARD hour = leveltime / (TICRATE * 360); minute = leveltime / (TICRATE * 60); second = leveltime / TICRATE; if (hour) snprintf(SlotText[option], SLOTTEXTLEN + 2, "E%iM%i %02i:%02iH", gameepisode, gamemap, hour, minute % 60); else snprintf(SlotText[option], SLOTTEXTLEN + 2, "E%iM%i %02i:%02iM", gameepisode, gamemap, minute, second % 60); #endif ptr = SlotText[option]; while (*ptr) { ptr++; } *ptr = '['; *(ptr + 1) = 0; SlotStatus[option]++; currentSlot = option; slotptr = ptr - SlotText[option]; return false; } else { G_SaveGame(option, SlotText[option]); FileMenuKeySteal = false; MN_DeactivateMenu(); } BorderNeedRefresh = true; if (quicksave == -1) { quicksave = option + 1; players[consoleplayer].message = NULL; players[consoleplayer].messageTics = 1; } return true; }
static void LoadChexDeh(void) { char *chex_deh = NULL; char *sep; if (gameversion == exe_chex) { // Look for chex.deh in the same directory as the IWAD file. sep = strrchr(iwadfile, DIR_SEPARATOR); if (sep != NULL) { size_t chex_deh_len = strlen(iwadfile) + 9; chex_deh = malloc(chex_deh_len); M_StringCopy(chex_deh, iwadfile, chex_deh_len); chex_deh[sep - iwadfile + 1] = '\0'; M_StringConcat(chex_deh, "chex.deh", chex_deh_len); } else { chex_deh = strdup("chex.deh"); } // If the dehacked patch isn't found, try searching the WAD // search path instead. We might find it... if (!M_FileExists(chex_deh)) { free(chex_deh); chex_deh = D_FindWADByName("chex.deh"); } // Still not found? if (chex_deh == NULL) { I_Error("Unable to find Chex Quest dehacked file (chex.deh).\n" "The dehacked file is required in order to emulate\n" "chex.exe correctly. It can be found in your nearest\n" "/idgames repository mirror at:\n\n" " utils/exe_edit/patches/chexdeh.zip"); } if (!DEH_LoadFile(chex_deh)) { I_Error("Failed to load chex.deh needed for emulating chex.exe."); } } }
void W_NWTDashMerge(char *filename) { wad_file_t *wad_file; int old_numlumps; int i; old_numlumps = numlumps; // Load PWAD wad_file = W_AddFile(filename); if (wad_file == NULL) { return; } // IWAD is at the start, PWAD was appended to the end iwad.lumps = lumpinfo; iwad.numlumps = old_numlumps; pwad.lumps = lumpinfo + old_numlumps; pwad.numlumps = numlumps - old_numlumps; // Setup sprite/flat lists SetupLists(); // Search through the IWAD sprites list. for (i=0; i<iwad_sprites.numlumps; ++i) { if (FindInList(&pwad, iwad_sprites.lumps[i]->name) >= 0) { // Replace this entry with an empty string. This is what // nwt -merge does. M_StringCopy(iwad_sprites.lumps[i]->name, "", 8); } } // Discard PWAD // The PWAD must now be added in again with -file. numlumps = old_numlumps; W_CloseFile(wad_file); }
void SC_Open(char *name) { static char StringBuffer[MAX_STRING_SIZE]; SC_Close(); ScriptLumpNum = W_GetNumForName(name); ScriptBuffer = W_CacheLumpNum(ScriptLumpNum); M_StringCopy(ScriptName, name, sizeof(ScriptName)); ScriptPtr = ScriptBuffer; ScriptEndPtr = ScriptPtr + W_LumpLength(ScriptLumpNum); sc_Line = 1; sc_End = false; ScriptOpen = true; sc_String = StringBuffer; AlreadyGot = false; }
char *M_StringJoin(const char *s, ...) { char *result; const char *v; va_list args; size_t result_len; result_len = strlen(s) + 1; va_start(args, s); for (;;) { v = va_arg(args, const char *); if (v == NULL) { break; } result_len += strlen(v); } va_end(args); result = malloc(result_len); if (result == NULL) { I_Error("M_StringJoin: Failed to allocate new string."); return NULL; } M_StringCopy(result, s, result_len); va_start(args, s); for (;;) { v = va_arg(args, const char *); if (v == NULL) { break; } M_StringConcat(result, v, result_len); } va_end(args); return result; }
static void QueryResponseCallback(net_addr_t *addr, net_querydata_t *querydata, unsigned int ping_time, TXT_UNCAST_ARG(results_table)) { TXT_CAST_ARG(txt_table_t, results_table); char ping_time_str[16]; char description[47]; // When we connect we'll have to negotiate a common protocol that we // can agree upon between the client and server. If we can't then we // won't be able to connect, so it's pointless to include it in the // results list. If protocol==NET_PROTOCOL_UNKNOWN then this may be // an old, pre-3.0 Chocolate Doom server that doesn't support the new // protocol negotiation mechanism, or it may be an incompatible fork. if (querydata->protocol == NET_PROTOCOL_UNKNOWN) { return; } M_snprintf(ping_time_str, sizeof(ping_time_str), "%ims", ping_time); // Build description from server name field. Because there is limited // space, we only include the player count if there are already players // connected to the server. if (querydata->num_players > 0) { M_snprintf(description, sizeof(description), "(%d/%d) ", querydata->num_players, querydata->max_players); } else { M_StringCopy(description, "", sizeof(description)); } M_StringConcat(description, querydata->description, sizeof(description)); TXT_AddWidgets(results_table, TXT_NewLabel(ping_time_str), TXT_NewButton2(NET_AddrToString(addr), SelectQueryAddress, querydata), TXT_NewLabel(description), NULL); ++query_servers_found; }
// // Draw character quit prompt // void FE_DrawChar(void) { char msg[128]; if(!curCharacter) return; V_DrawPatch(0, 0, W_CacheLumpName(curCharacter->pic, PU_CACHE)); M_WriteText(12, 18, curCharacter->name); M_StringCopy(msg, curCharacter->text, sizeof(msg)); M_DialogDimMsg(20, 28, msg, false); M_WriteText(20, 28, msg); FE_WriteSmallTextCentered(160, "Are you sure you want to quit?"); FE_WriteSmallTextCentered(172, "(Press Y or confirm to quit)"); }
static boolean SCSaveGame(int option) { char *ptr; if (!FileMenuKeySteal) { int x, y; FileMenuKeySteal = true; // We need to activate the text input interface to type the save // game name: x = SaveMenu.x + 1; y = SaveMenu.y + 1 + option * ITEM_HEIGHT; I_StartTextInput(x, y, x + 190, y + ITEM_HEIGHT - 2); M_StringCopy(oldSlotText, SlotText[option], sizeof(oldSlotText)); ptr = SlotText[option]; while (*ptr) { ptr++; } *ptr = '['; *(ptr + 1) = 0; SlotStatus[option]++; currentSlot = option; slotptr = ptr - SlotText[option]; return false; } else { G_SaveGame(option, SlotText[option]); FileMenuKeySteal = false; I_StopTextInput(); MN_DeactivateMenu(); } BorderNeedRefresh = true; if (quicksave == -1) { quicksave = option + 1; players[consoleplayer].message = NULL; players[consoleplayer].messageTics = 1; } return true; }
static void TXT_JoystickAxisDrawer(TXT_UNCAST_ARG(joystick_axis)) { TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); char buf[JOYSTICK_AXIS_WIDTH + 1]; int i; if (*joystick_axis->axis < 0) { M_StringCopy(buf, "(none)", sizeof(buf)); } else if (IS_BUTTON_AXIS(*joystick_axis->axis)) { int neg, pos; neg = BUTTON_AXIS_NEG(*joystick_axis->axis); pos = BUTTON_AXIS_POS(*joystick_axis->axis); M_snprintf(buf, sizeof(buf), "BUTTONS #%i+#%i", neg, pos); } else if (IS_HAT_AXIS(*joystick_axis->axis)) { int hat, dir; hat = HAT_AXIS_HAT(*joystick_axis->axis); dir = HAT_AXIS_DIRECTION(*joystick_axis->axis); M_snprintf(buf, sizeof(buf), "HAT #%i (%s)", hat, dir == HAT_AXIS_HORIZONTAL ? "horizontal" : "vertical"); } else { M_snprintf(buf, sizeof(buf), "AXIS #%i", *joystick_axis->axis); } TXT_SetWidgetBG(joystick_axis); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(buf); for (i = TXT_UTF8_Strlen(buf); i < joystick_axis->widget.w; ++i) { TXT_DrawString(" "); } }
deh_context_t *DEH_OpenLump(int lumpnum) { deh_context_t *context; void *lump; lump = W_CacheLumpNum(lumpnum, PU_STATIC); context = DEH_NewContext(); context->type = DEH_INPUT_LUMP; context->lumpnum = lumpnum; context->input_buffer = lump; context->input_buffer_len = W_LumpLength(lumpnum); context->input_buffer_pos = 0; context->filename = malloc(9); M_StringCopy(context->filename, lumpinfo[lumpnum].name, 9); return context; }
static void PlayerQuitGame(player_t *player) { static char exitmsg[80]; unsigned int player_num; player_num = player - players; M_StringCopy(exitmsg, "PLAYER 1 LEFT THE GAME", sizeof(exitmsg)); exitmsg[7] += player_num; P_SetMessage(&players[consoleplayer], exitmsg, true); S_StartSound(NULL, SFX_CHAT); playeringame[player_num] = false; // TODO: check if it is sensible to do this: if (demorecording) { G_CheckDemoStatus (); } }
static void GetSfxLumpName(sfxinfo_t *sfx, char *buf, size_t buf_len) { // Linked sfx lumps? Get the lump number for the sound linked to. if (sfx->link != NULL) { sfx = sfx->link; } // Doom adds a DS* prefix to sound lumps; Heretic and Hexen don't // do this. if (use_sfx_prefix) { M_snprintf(buf, buf_len, "ds%s", DEH_String(sfx->name)); } else { M_StringCopy(buf, DEH_String(sfx->name), buf_len); } }
static void QueryResponseCallback(net_addr_t *addr, net_querydata_t *querydata, unsigned int ping_time, TXT_UNCAST_ARG(results_table)) { TXT_CAST_ARG(txt_table_t, results_table); char ping_time_str[16]; char description[47]; M_snprintf(ping_time_str, sizeof(ping_time_str), "%ims", ping_time); M_StringCopy(description, querydata->description, sizeof(description)); TXT_AddWidgets(results_table, TXT_NewLabel(ping_time_str), TXT_NewButton2(NET_AddrToString(addr), SelectQueryAddress, querydata), TXT_NewLabel(description), NULL); ++query_servers_found; }
static void OpenScript(char *name, int type) { SC_Close(); if (type == LUMP_SCRIPT) { // Lump script ScriptLumpNum = W_GetNumForName(name); ScriptBuffer = (char *) W_CacheLumpNum(ScriptLumpNum, PU_STATIC); ScriptSize = W_LumpLength(ScriptLumpNum); M_StringCopy(ScriptName, name, sizeof(ScriptName)); } else if (type == FILE_ZONE_SCRIPT) { // File script - zone ScriptLumpNum = -1; ScriptSize = M_ReadFile(name, (byte **) & ScriptBuffer); M_ExtractFileBase(name, ScriptName); } ScriptPtr = ScriptBuffer; ScriptEndPtr = ScriptPtr + ScriptSize; sc_Line = 1; sc_End = false; ScriptOpen = true; sc_String = StringBuffer; AlreadyGot = false; }
// // P_GiveItemToPlayer // // [STRIFE] New function // haleyjd 09/03/10: Sorts out how to give something to the player. // Not strictly just for inventory items. // villsa 09/09/10: Fleshed out function // boolean P_GiveItemToPlayer(player_t *player, int sprnum, mobjtype_t type) { int i = 0; line_t junk; int sound = sfx_itemup; // haleyjd 09/21/10: different sounds for items // set quest if mf_givequest flag is set if(mobjinfo[type].flags & MF_GIVEQUEST) player->questflags |= 1 << (mobjinfo[type].speed - 1); // check for keys if(type >= MT_KEY_BASE && type <= MT_NEWKEY5) { P_GiveCard(player, type - MT_KEY_BASE); return true; } // check for quest tokens if(type >= MT_TOKEN_QUEST1 && type <= MT_TOKEN_QUEST31) { if(mobjinfo[type].name) { M_StringCopy(pickupstring, DEH_String(mobjinfo[type].name), 39); player->message = pickupstring; } player->questflags |= 1 << (type - MT_TOKEN_QUEST1); if(player == &players[consoleplayer]) S_StartSound(NULL, sound); return true; } // haleyjd 09/22/10: Refactored to give sprites higher priority than // mobjtypes and to implement missing logic. switch(sprnum) { case SPR_HELT: // This is given only by the "DONNYTRUMP" cheat (aka Midas) P_GiveInventoryItem(player, SPR_HELT, MT_TOKEN_TOUGHNESS); P_GiveInventoryItem(player, SPR_GUNT, MT_TOKEN_ACCURACY); // [STRIFE] Bizarre... for(i = 0; i < 5 * player->accuracy + 300; i++) P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); break; case SPR_ARM1: // Armor 1 if(!P_GiveArmor(player, -2)) P_GiveInventoryItem(player, sprnum, type); break; case SPR_ARM2: // Armor 2 if(!P_GiveArmor(player, -1)) P_GiveInventoryItem(player, sprnum, type); break; case SPR_COIN: // 1 Gold P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); break; case SPR_CRED: // 10 Gold for(i = 0; i < 10; i++) P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); break; case SPR_SACK: // 25 gold for(i = 0; i < 25; i++) P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); break; case SPR_CHST: // 50 gold for(i = 0; i < 50; i++) P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); case SPR_BBOX: // Box of Bullets if(!P_GiveAmmo(player, am_bullets, 5)) return false; break; case SPR_BLIT: // Bullet Clip if(!P_GiveAmmo(player, am_bullets, 1)) return false; break; case SPR_PMAP: // Map powerup if(!P_GivePower(player, pw_allmap)) return false; sound = sfx_yeah; // bluh-doop! break; case SPR_COMM: // Communicator if(!P_GivePower(player, pw_communicator)) return false; sound = sfx_yeah; // bluh-doop! break; case SPR_MSSL: // Mini-missile if(!P_GiveAmmo(player, am_missiles, 1)) return false; break; case SPR_ROKT: // Crate of missiles if(!P_GiveAmmo(player, am_missiles, 5)) return false; break; case SPR_BRY1: // Battery cell if(!P_GiveAmmo(player, am_cell, 1)) return false; break; case SPR_CPAC: // Cell pack if(!P_GiveAmmo(player, am_cell, 5)) return false; break; case SPR_PQRL: // Poison bolts if(!P_GiveAmmo(player, am_poisonbolts, 5)) return false; break; case SPR_XQRL: // Electric bolts if(!P_GiveAmmo(player, am_elecbolts, 5)) return false; break; case SPR_GRN1: // HE Grenades if(!P_GiveAmmo(player, am_hegrenades, 1)) return false; break; case SPR_GRN2: // WP Grenades if(!P_GiveAmmo(player, am_wpgrenades, 1)) return false; break; case SPR_BKPK: // Backpack (aka Ammo Satchel) if(!player->backpack) { for(i = 0; i < NUMAMMO; i++) player->maxammo[i] *= 2; player->backpack = true; } for(i = 0; i < NUMAMMO; i++) P_GiveAmmo(player, i, 1); break; case SPR_RIFL: // Assault Rifle if(player->weaponowned[wp_rifle]) return false; if(!P_GiveWeapon(player, wp_rifle, false)) return false; sound = sfx_wpnup; // SHK-CHK! break; case SPR_FLAM: // Flamethrower if(player->weaponowned[wp_flame]) return false; if(!P_GiveWeapon(player, wp_flame, false)) return false; sound = sfx_wpnup; // SHK-CHK! break; case SPR_MMSL: // Mini-missile Launcher if(player->weaponowned[wp_missile]) return false; if(!P_GiveWeapon(player, wp_missile, false)) return false; sound = sfx_wpnup; // SHK-CHK! break; case SPR_TRPD: // Mauler if(player->weaponowned[wp_mauler]) return false; if(!P_GiveWeapon(player, wp_mauler, false)) return false; sound = sfx_wpnup; // SHK-CHK! break; case SPR_CBOW: // Here's a crossbow. Just aim straight, and *SPLAT!* if(player->weaponowned[wp_elecbow]) return false; if(!P_GiveWeapon(player, wp_elecbow, false)) return false; sound = sfx_wpnup; // SHK-CHK! break; case SPR_TOKN: // Miscellaneous items - These are determined by thingtype. switch(type) { case MT_KEY_HAND: // Severed hand P_GiveCard(player, key_SeveredHand); break; case MT_MONY_300: // 300 Gold (this is the only way to get it, in fact) for(i = 0; i < 300; i++) P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); break; case MT_TOKEN_AMMO: // Ammo token - you get this from the Weapons Trainer if(player->ammo[am_bullets] >= 50) return false; player->ammo[am_bullets] = 50; break; case MT_TOKEN_HEALTH: // Health token - from the Front's doctor if(!P_GiveBody(player, healthamounts[gameskill])) return false; break; case MT_TOKEN_ALARM: // Alarm token - particularly from the Oracle. P_NoiseAlert(player->mo, player->mo); A_AlertSpectreC(dialogtalker); // BUG: assumes in a dialog o_O break; case MT_TOKEN_DOOR1: // Door special 1 junk.tag = 222; EV_DoDoor(&junk, vld_open); break; case MT_TOKEN_PRISON_PASS: // Door special 1 - Prison pass junk.tag = 223; EV_DoDoor(&junk, vld_open); if(gamemap == 2) // If on Tarnhill, give Prison pass object P_GiveInventoryItem(player, sprnum, type); break; case MT_TOKEN_SHOPCLOSE: // Door special 3 - "Shop close" - unused? junk.tag = 222; EV_DoDoor(&junk, vld_close); break; case MT_TOKEN_DOOR3: // Door special 4 (or 3? :P ) junk.tag = 224; EV_DoDoor(&junk, vld_close); break; case MT_TOKEN_STAMINA: // Stamina upgrade if(player->stamina >= 100) return false; player->stamina += 10; P_GiveBody(player, 200); // full healing break; case MT_TOKEN_NEW_ACCURACY: // Accuracy upgrade if(player->accuracy >= 100) return false; player->accuracy += 10; break; case MT_SLIDESHOW: // Slideshow (start a finale) gameaction = ga_victory; if(gamemap == 10) P_GiveItemToPlayer(player, SPR_TOKN, MT_TOKEN_QUEST17); break; default: // The default is to just give it as an inventory item. P_GiveInventoryItem(player, sprnum, type); break; } break; default: // The ultimate default: Give it as an inventory item. if(!P_GiveInventoryItem(player, sprnum, type)) return false; break; } // Play sound. if(player == &players[consoleplayer]) S_StartSound(NULL, sound); return true; }
// // P_DialogDoChoice // // [STRIFE] New function // haleyjd 09/05/10: Handles making a choice in a dialog. Installed as the // callback for all items in the dialogmenu structure. // void P_DialogDoChoice(int choice) { int i = 0, nextdialog = 0; boolean candochoice = true; char *message = NULL; mapdlgchoice_t *currentchoice; if(choice == -1) choice = dialogmenu.numitems - 1; currentchoice = &(currentdialog->choices[choice]); I_StartVoice(NULL); // STRIFE-TODO: verify (should stop previous voice I believe) // villsa 09/08/10: converted into for loop for(i = 0; i < MDLG_MAXITEMS; i++) { if(P_PlayerHasItem(dialogplayer, currentchoice->needitems[i]) < currentchoice->needamounts[i]) { candochoice = false; // nope, missing something } } if(choice != dialogmenu.numitems - 1 && candochoice) { int item; message = currentchoice->textok; if(dialogtalkerstates->yes) P_SetMobjState(dialogtalker, dialogtalkerstates->yes); item = currentchoice->giveitem; if(item < 0 || P_GiveItemToPlayer(dialogplayer, states[mobjinfo[item].spawnstate].sprite, item)) { // if successful, take needed items int count = 0; // villsa 09/08/10: converted into for loop for(count = 0; count < MDLG_MAXITEMS; count++) { P_TakeDialogItem(dialogplayer, currentchoice->needitems[count], currentchoice->needamounts[count]); } } else message = DEH_String("You seem to have enough!"); // store next dialog into the talking actor nextdialog = currentchoice->next; if(nextdialog != 0) dialogtalker->miscdata = (byte)(abs(nextdialog)); } else { // not successful message = currentchoice->textno; if(dialogtalkerstates->no) P_SetMobjState(dialogtalker, dialogtalkerstates->no); } if(choice != dialogmenu.numitems - 1) { int objective; char *objlump; if((objective = currentchoice->objective)) { DEH_snprintf(mission_objective, OBJECTIVE_LEN, "log%i", objective); objlump = W_CacheLumpName(mission_objective, PU_CACHE); M_StringCopy(mission_objective, objlump, OBJECTIVE_LEN); } // haleyjd 20130301: v1.31 hack: if first char of message is a period, // clear the player's message. Is this actually used anywhere? if(gameversion == exe_strife_1_31 && message[0] == '.') message = NULL; dialogplayer->message = message; } dialogtalker->angle = dialogtalkerangle; dialogplayer->st_update = true; M_ClearMenus(0); if(nextdialog >= 0 || gameaction == ga_victory) // Macil hack menuindialog = false; else P_DialogStart(dialogplayer); }
// // P_DialogDrawer // // This function is set as the drawer callback for the dialog menu. // static void P_DialogDrawer(void) { angle_t angle; int y; int i; int height; int finaly; char choicetext[64]; char choicetext2[64]; // Run down bonuscount faster than usual so that flashes from being given // items are less obvious. if(dialogplayer->bonuscount) { dialogplayer->bonuscount -= 3; if(dialogplayer->bonuscount < 0) dialogplayer->bonuscount = 0; } angle = R_PointToAngle2(dialogplayer->mo->x, dialogplayer->mo->y, dialogtalker->x, dialogtalker->y); angle -= dialogplayer->mo->angle; // Dismiss the dialog if the player is out of alignment, or the thing he was // talking to is now engaged in battle. if ((angle > ANG45 && angle < (ANG270+ANG45)) || (dialogtalker->flags & MF_NODIALOG) != 0) { P_DialogDoChoice(dialogmenu.numitems - 1); } dialogtalker->reactiontime = 2; // draw background if(dialogbgpiclumpnum != -1) { patch_t *patch = W_CacheLumpNum(dialogbgpiclumpnum, PU_CACHE); V_DrawPatchDirect(0, 0, patch); } // if there's a valid background pic, delay drawing the rest of the menu // for a while; otherwise, it will appear immediately if(dialogbgpiclumpnum == -1 || menupausetime <= gametic) { if(menuindialog) { // time to pause the game? if(menupausetime + 3 < gametic) menupause = true; } // draw character name M_WriteText(12, 18, dialogname); y = 28; // show text (optional for dialogs with voices) if(dialogshowtext || currentdialog->voice[0] == '\0') y = M_WriteText(20, 28, dialogtext); height = 20 * dialogmenu.numitems; finaly = 175 - height; // preferred height if(y > finaly) finaly = 199 - height; // height it will bump down to if necessary. // draw divider M_WriteText(42, finaly - 6, DEH_String("______________________________")); dialogmenu.y = finaly + 6; y = 0; // draw the menu items for(i = 0; i < dialogmenu.numitems - 1; i++) { DEH_snprintf(choicetext, sizeof(choicetext), "%d) %s", i + 1, currentdialog->choices[i].text); // alternate text for items that need money if(currentdialog->choices[i].needamounts[0] > 0) { // haleyjd 20120401: necessary to avoid undefined behavior: M_StringCopy(choicetext2, choicetext, sizeof(choicetext2)); DEH_snprintf(choicetext, sizeof(choicetext), "%s for %d", choicetext2, currentdialog->choices[i].needamounts[0]); } M_WriteText(dialogmenu.x, dialogmenu.y + 3 + y, choicetext); y += 19; } // draw the final item for dismissing the dialog M_WriteText(dialogmenu.x, 19 * i + dialogmenu.y + 3, dialoglastmsgbuffer); } }
void CT_Ticker(void) { int i; int j; char c; int numplayers; for (i = 0; i < maxplayers; i++) { if (!playeringame[i]) { continue; } if ((c = players[i].cmd.chatchar) != 0) { if (c <= CT_PLR_ALL) { chat_dest[i] = c; continue; } else if (c == CT_ESCAPE) { CT_ClearChatMessage(i); } else if (c == KEY_ENTER) { numplayers = 0; for (j = 0; j < maxplayers; j++) { numplayers += playeringame[j]; } CT_AddChar(i, 0); // set the end of message character if (numplayers > 2) { M_StringCopy(plr_lastmsg[i], CT_FromPlrText[i], sizeof(plr_lastmsg[i])); M_StringConcat(plr_lastmsg[i], chat_msg[i], sizeof(plr_lastmsg[i])); } else { M_StringCopy(plr_lastmsg[i], chat_msg[i], sizeof(plr_lastmsg[i])); } if (i != consoleplayer && (chat_dest[i] == consoleplayer + 1 || chat_dest[i] == CT_PLR_ALL) && *chat_msg[i]) { P_SetMessage(&players[consoleplayer], plr_lastmsg[i], true); S_StartSound(NULL, SFX_CHAT); } else if (i == consoleplayer && (*chat_msg[i])) { if (numplayers <= 1) { P_SetMessage(&players[consoleplayer], "THERE ARE NO OTHER PLAYERS IN THE GAME!", true); S_StartSound(NULL, SFX_CHAT); } } CT_ClearChatMessage(i); } else if (c == KEY_BACKSPACE) { CT_BackSpace(i); } else { CT_AddChar(i, c); } } } return; }