qboolean Pickup_Rune (edict_t *ent, edict_t *other) { item_t *slot; if (!other->client) return false; //Show the user what kind of rune it is if (level.time > other->msg_time) { V_PrintItemProperties(other, &ent->vrxitem); other->msg_time = level.time+1; } if (other->client->rune_delay > level.time) return false; //4.2 if it's worthless, then just destroy it if (ent->vrxitem.itemLevel < 1) { G_FreeEdict(ent); return false; } //Can we pick it up? if (!V_CanPickUpItem(other)) return false; //Give them the rune slot = V_FindFreeItemSlot(other); V_ItemCopy(&ent->vrxitem, slot); //Save the player file (prevents lost runes) if (savemethod->value == 1) SaveCharacter(other); else if (savemethod->value == 0) { char path[MAX_QPATH]; memset(path, 0, MAX_QPATH); VRXGetPath(path, other); VSF_SaveRunes(other, path); } other->client->rune_delay = level.time + RUNE_PICKUP_DELAY; //Done return true; }
void BuyRuneConfirmMenu_handler (edict_t *ent, int option) { //Navigating the menu? if (option > 100) { int page_num = option / 1000; int selection = (option % 1000)-1; item_t *slot = V_FindFreeItemSlot(ent); int cost; armoryRune_t *firstItem; item_t *rune; switch(page_num) { case 1: firstItem = WeaponRunes; break; case 2: firstItem = AbilityRunes; break; case 3: firstItem = ComboRunes; break; default: gi.dprintf("Error in BuyRuneConfirmMenu_handler(). Invalid page number: %d\n", page_num); return; } rune = &((firstItem + selection)->rune); if (rune->itemtype == ITEM_NONE) { gi.cprintf(ent, PRINT_HIGH, "Sorry, someone else has purchased this rune.\n"); closemenu(ent); return; } cost = getBuyValue(rune); //Do we have enough credits? if (ent->myskills.credits < cost) { gi.cprintf(ent, PRINT_HIGH, "You need %d more credits to buy this item.\n", cost - ent->myskills.credits); } //Check for free space else if (slot == NULL) { gi.cprintf(ent, PRINT_HIGH, "Not enough room in inventory.\n"); } else { //log the purchase WriteToLogfile(ent, va("Buying rune for %d credits. [%s]", cost, rune->id)); //Buy it! V_ItemSwap(rune, slot); ent->myskills.credits -= cost; SaveArmory(); savePlayer(ent); gi.cprintf(ent, PRINT_HIGH, "Rune purchased for %d credits.\nYou have %d credits left.\n", cost, ent->myskills.credits); gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/gold.wav"), 1, ATTN_NORM, 0); } //done closemenu(ent); return; } else { int page_num = option / 10; int selection = option % 10; OpenBuyRuneMenu(ent, page_num, selection); return; } }
void Cmd_Armory_f(edict_t *ent, int selection) { int cur_credits=ent->myskills.credits; gitem_t *item = 0; int price = 0; int qty = 0; item_t *slot; int type = ITEM_NONE; //int talentLevel; if (ent->deadflag == DEAD_DEAD) return; //What is the price/qty of the item? if ((selection < 11) && (selection > 0)) price = ARMORY_PRICE_WEAPON; else if (selection < 17) price = ARMORY_PRICE_AMMO; switch(selection) { //weapons case 1: item = FindItem("Shotgun"); break; //sg case 2: item = FindItem("Super Shotgun"); break; //ssg case 3: item = FindItem("Machinegun"); break; //mg case 4: item = FindItem("Chaingun"); break; //cg case 5: item = FindItem("Grenade Launcher");break; //gl case 6: item = FindItem("Rocket Launcher"); break; //rl case 7: item = FindItem("Hyperblaster"); break; //hb case 8: item = FindItem("Railgun"); break; //rg case 9: item = FindItem("bfg10k"); break; //bfg case 10: item = FindItem("20mm Cannon"); break; //20mm //ammo case 11: item = FindItem("Bullets"); qty = ent->client->pers.max_bullets; break; case 12: item = FindItem("Shells"); qty = ent->client->pers.max_shells; break; case 13: item = FindItem("Cells"); qty = ent->client->pers.max_cells; break; case 14: item = FindItem("Grenades"); qty = ent->client->pers.max_grenades; break; case 15: item = FindItem("Rockets"); qty = ent->client->pers.max_rockets; break; case 16: item = FindItem("Slugs"); qty = ent->client->pers.max_slugs; break; //others case 17: //tballs price = ARMORY_PRICE_TBALLS; item = FindItem("tballs"); qty = ent->client->pers.max_tballs; break; case 18: //4.5 replaced respawns with health price = ARMORY_PRICE_HEALTH; qty = ent->max_health - ent->health; break; case 19: //power cubes qty = MAX_POWERCUBES(ent) - ent->client->pers.inventory[ITEM_INDEX(Fdi_POWERCUBE)]; //Base the price on how many cubes the player needs. price = qty * ARMORY_PRICE_POWERCUBE; break; case 20: //armor price = ARMORY_PRICE_ARMOR; item = FindItem("Body Armor"); qty = MAX_ARMOR(ent); break; case 21: //health potions type = ITEM_POTION; price = ARMORY_PRICE_POTIONS; qty = ARMORY_QTY_POTIONS; slot = V_FindFreeItemSlot(ent); break; case 22: //antidotes type = ITEM_ANTIDOTE; price = ARMORY_PRICE_ANTIDOTES; qty = ARMORY_QTY_ANTIDOTES; slot = V_FindFreeItemSlot(ent); break; case 23: //grav boots type = ITEM_GRAVBOOTS; price = ARMORY_PRICE_GRAVITYBOOTS; qty = ARMORY_QTY_GRAVITYBOOTS; slot = V_FindFreeItemSlot(ent); break; case 24: //fire resistant clothing type = ITEM_FIRE_RESIST; price = ARMORY_PRICE_FIRE_RESIST; qty = ARMORY_QTY_FIRE_RESIST; slot = V_FindFreeItemSlot(ent); break; case 25: //auto-tball type = ITEM_AUTO_TBALL; price = ARMORY_PRICE_AUTO_TBALL; qty = ARMORY_QTY_AUTO_TBALL; slot = V_FindFreeItemSlot(ent); break; //Runes case 26: //ability rune PurchaseRandomRune(ent, ITEM_ABILITY); return; case 27: //weapon rune PurchaseRandomRune(ent, ITEM_WEAPON); return; case 28: //reset char data price = ARMORY_PRICE_RESET*ent->myskills.level; if (price > 50000) price = 50000; break; default: gi.dprintf("ERROR: Invalid armory item!\n"); return; } //Talent: Bartering //talentLevel = getTalentLevel(ent, TALENT_BARTERING); //if(talentLevel > 0) price *= 1.0 - 0.05 * talentLevel; if (cur_credits > MAX_CREDITS+10000) { // as of version 3.13, we can only handle up to 65,535 (unsigned int) credits // if we have much more than this, then the player's credits probably got corrupted gi.dprintf("WARNING: Cmd_Armory_f corrected invalid player credits\n"); gi.cprintf(ent, PRINT_HIGH, "Your credits were fixed.\n"); ent->myskills.credits = 0; return; } if (cur_credits < price) { gi.cprintf(ent, PRINT_HIGH, "You need at least %d credits to buy this item.\n", price); return; } //If a weapon was purchased if ((selection < 11) && (selection > 0)) { ent->client->pers.inventory[ITEM_INDEX(item)] = 1; gi.cprintf(ent, PRINT_HIGH, "You bought a %s.\n", item->pickup_name); } //If ammo was purchased (or T-Balls) else if (selection < 18) { ent->client->pers.inventory[ITEM_INDEX(item)] = qty; gi.cprintf(ent, PRINT_HIGH, "You bought %d %s.\n", qty, item->pickup_name); } //Something else was selected else { switch(selection) { case 18: //4.5 health { if (ent->health >= ent->max_health) { gi.cprintf(ent, PRINT_HIGH, "You don't need health.\n"); return; } ent->health = ent->max_health; gi.cprintf(ent, PRINT_HIGH, "You bought %d health.\n", qty); } break; case 19: //Power Cubes { if (qty < 1) { gi.cprintf(ent, PRINT_HIGH, "You don't need power cubes.\n"); return; } ent->client->pers.inventory[ITEM_INDEX(Fdi_POWERCUBE)] += qty; gi.cprintf(ent, PRINT_HIGH, "You bought %d power cubes.\n", qty); } break; case 20: //armor { if (ent->client->pers.inventory[ITEM_INDEX(item)] < MAX_ARMOR(ent)) { ent->client->pers.inventory[ITEM_INDEX(item)] += 100; if (ent->client->pers.inventory[ITEM_INDEX(item)] > MAX_ARMOR(ent)) ent->client->pers.inventory[ITEM_INDEX(item)] = MAX_ARMOR(ent); gi.cprintf(ent, PRINT_HIGH, "You bought some armor.\n"); } else { gi.cprintf(ent, PRINT_HIGH, "You are maxed out on armor already.\n"); return; } } break; // handle all the new items in the same way case 21: //Health Potions case 22: //Antidote Potions (Holy Water) case 23: //Anti-Grav boots case 24: //Fire resist clothing case 25: //Auto-tball { if (slot == NULL) { gi.cprintf(ent, PRINT_HIGH, "Not enough inventory space.\n"); return; } //4.0 Players can't buy too many stackable items if(V_ItemCount(ent, type) >= ARMORY_MAX_CONSUMABLES) { gi.cprintf(ent, PRINT_HIGH, va("You can't buy more than %d of these items.\n", ARMORY_MAX_CONSUMABLES)); return; } //Give them the item V_ItemClear(slot); slot->itemLevel = 0; slot->itemtype = type; slot->quantity = qty; //Tell the user what they bought switch(selection) { case 21: gi.cprintf(ent, PRINT_HIGH, "You bought %d health potions.\n", qty); break; case 22: gi.cprintf(ent, PRINT_HIGH, "You bought %d vials of holy water.\n", qty); break; case 23: gi.cprintf(ent, PRINT_HIGH, "You bought a pair of anti-gravity boots.\n"); break; case 24: gi.cprintf(ent, PRINT_HIGH, "You bought some fire resistant clothing.\n"); break; case 25: gi.cprintf(ent, PRINT_HIGH, "You bought an Auto-Tball.\n"); break; } } break; case 28: //Reset char data ChangeClass(ent->client->pers.netname, ent->myskills.class_num, 2); break; } } //spend the credits ent->myskills.credits -= price; gi.cprintf(ent, PRINT_HIGH, "You now have %d credits left. \n", ent->myskills.credits); gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/gold.wav"), 1, ATTN_NORM, 0); }
void PurchaseRandomRune(edict_t *ent, int runetype) { int cost; edict_t *rune; item_t *slot; char buf[64]; cost = RUNE_COST_BASE + RUNE_COST_ADDON * ent->myskills.level; if (ent->myskills.credits < cost) { safe_cprintf(ent, PRINT_HIGH, "You need %d credits to purchase a rune.\n", cost); return; } slot = V_FindFreeItemSlot(ent); if (!slot) { safe_cprintf(ent, PRINT_HIGH, "Not enough inventory space!\n"); return; } // rune pick-up delay if (ent->client->rune_delay > level.time) return; rune = G_Spawn(); // create a rune V_ItemClear(&rune->vrxitem); // initialize the rune ent->myskills.credits -= cost; if (runetype) { spawnNorm(rune, ent->myskills.level, runetype); } else if (random() > 0.5) { spawnNorm(rune, ent->myskills.level, ITEM_WEAPON); } else { spawnNorm(rune, ent->myskills.level, ITEM_ABILITY); } if (Pickup_Rune(rune, ent) == false) { G_FreeEdict(rune); //gi.dprintf("WARNING: PurchaseRandomRune() was unable to spawn a rune\n"); return; } G_FreeEdict(rune); //Find out what the player bought strcpy(buf, GetRuneValString(slot)); switch(slot->itemtype) { case ITEM_WEAPON: strcat(buf, va(" weapon rune (%d mods)", slot->numMods)); break; case ITEM_ABILITY: strcat(buf, va(" ability rune (%d mods)", slot->numMods)); break; case ITEM_COMBO: strcat(buf, va(" combo rune (%d mods)", slot->numMods)); break; } //send the message to the player safe_cprintf(ent, PRINT_HIGH, "You bought a %s.\n", buf); safe_cprintf(ent, PRINT_HIGH, "You now have %d credits left. \n", ent->myskills.credits); gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/gold.wav"), 1, ATTN_NORM, 0); //Save the player if (savemethod->value == 1) SaveCharacter(ent); else if (savemethod->value == 0) { char path[MAX_QPATH]; memset(path, 0, MAX_QPATH); VRXGetPath(path, ent); VSF_SaveRunes(ent, path); }else if (savemethod->value == 3) { VSFU_SaveRunes(ent); } //write to the log gi.dprintf("INFO: %s purchased a level %d rune (%s).\n", ent->client->pers.netname, slot->itemLevel, slot->id); WriteToLogfile(ent, va("Purchased a level %d rune (%s) for %d credits. Player has %d credits left.\n", slot->itemLevel, slot->id, cost, ent->myskills.credits)); }
void V_EquipItem(edict_t *ent, int index) { int i, wpts, apts, total_pts, clvl = ent->myskills.level; // calculate number of weapon and ability points separately wpts = V_GetRuneWeaponPts(ent, &ent->myskills.items[index]); apts = V_GetRuneAbilityPts(ent, &ent->myskills.items[index]); // calculate weighted total total_pts = ceil(0.5*wpts + 0.75*apts);//was 0.66,2.0 //gi.dprintf("wpts = %d, apts = %d, total = %d\n", wpts, apts, total_pts); if(index < 3) { //remove an item item_t *slot = V_FindFreeItemSlot(ent); if (slot == NULL) { safe_cprintf(ent, PRINT_HIGH, "Not enough room in your stash.\n"); return; } V_ItemSwap(&ent->myskills.items[index], slot); gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/boots.wav"), 1, ATTN_NORM, 0); safe_cprintf(ent, PRINT_HIGH, "Item successfully placed in your stash.\n"); } //Everyone but admins have a minimum level requirement to use a rune. (easier for rune testing) // vrxchile 2.0: only 999 admins are able to test runes. else if ((ent->myskills.administrator < 999) && (ent->myskills.level < total_pts)) { safe_cprintf(ent, PRINT_HIGH, "You need to be level %d to use this rune.\n", total_pts); return; } else if (index < MAX_VRXITEMS) { int type = ent->myskills.items[index].itemtype; if (type & ITEM_UNIQUE) type ^= ITEM_UNIQUE; //equip an item switch(type) { case ITEM_WEAPON: V_ItemSwap(&ent->myskills.items[index], &ent->myskills.items[0]); //put on hand slot if (eqSetItems(ent, &ent->myskills.items[0]) == 3) gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/blessedaim.wav"), 1, ATTN_NORM, 0); else gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/glovesmetal.wav"), 1, ATTN_NORM, 0); break; case ITEM_ABILITY: V_ItemSwap(&ent->myskills.items[index], &ent->myskills.items[1]); //put on neck slot if (eqSetItems(ent, &ent->myskills.items[0]) == 3) gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/blessedaim.wav"), 1, ATTN_NORM, 0); else gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/amulet.wav"), 1, ATTN_NORM, 0); break; case ITEM_COMBO: V_ItemSwap(&ent->myskills.items[index], &ent->myskills.items[2]); //put on neck slot if (eqSetItems(ent, &ent->myskills.items[0]) == 3) gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/blessedaim.wav"), 1, ATTN_NORM, 0); else gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/belt.wav"), 1, ATTN_NORM, 0); break; case ITEM_CLASSRUNE: V_ItemSwap(&ent->myskills.items[index], &ent->myskills.items[1]); //put on neck slot if (eqSetItems(ent, &ent->myskills.items[0]) == 3) gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/blessedaim.wav"), 1, ATTN_NORM, 0); else gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/amulet.wav"), 1, ATTN_NORM, 0); break; } safe_cprintf(ent, PRINT_HIGH, "Item successfully equipped.\n"); } //Reset all rune info V_ResetAllStats(ent); for (i = 0; i < 3; ++i) { if (ent->myskills.items[i].itemtype != TYPE_NONE) V_ApplyRune(ent, &ent->myskills.items[i]); } }