int depot_give_item (edict_t *self, edict_t *other, int item_index) { int max, add, *p_inv, *d_inv; // max value that player can hold if (item_index == body_armor_index) max = MAX_ARMOR(other); else max = MaxAmmoType(other, item_index); p_inv = &other->client->pers.inventory[item_index]; // player current inventory count d_inv = &self->packitems[item_index]; // depot current inventory count add = max - *p_inv; // amount player needs // the player can't carry any more ammo if (add < 0) return 0; // can't add more than the depot has if (add > *d_inv) add = *d_inv; *p_inv += add; // add to player inventory *d_inv -= add; // reduce depot inventory //gi.dprintf("player: %d/%d depot: %d add: %d\n", *p_inv, max, *d_inv, add); return add; }
//*********************************************************************** // Save player v 1.0 //*********************************************************************** void WritePlayer_v1(FILE * fWrite, char *playername, edict_t *player) { int i; int numAbilities = CountAbilities(player); int numWeapons = CountWeapons(player); int numRunes = CountRunes(player); //save header WriteString(fWrite, "Vortex Player File v1.0"); //player's title WriteString(fWrite, player->myskills.title); //player's in-game name WriteString(fWrite, playername); //password WriteString(fWrite, player->myskills.password); //email address WriteString(fWrite, player->myskills.email); //owner WriteString(fWrite, player->myskills.owner); //creation date WriteString(fWrite, player->myskills.member_since); //last played date WriteString(fWrite, player->myskills.last_played); //playing time total WriteInteger(fWrite, player->myskills.total_playtime); //playing time today WriteInteger(fWrite, player->myskills.playingtime); //begin talents WriteInteger(fWrite, player->myskills.talents.count); for (i = 0; i < player->myskills.talents.count; ++i) { WriteInteger(fWrite, player->myskills.talents.talent[i].id); WriteInteger(fWrite, player->myskills.talents.talent[i].upgradeLevel); WriteInteger(fWrite, player->myskills.talents.talent[i].maxLevel); } //end talents //begin abilities WriteInteger(fWrite, numAbilities); for (i = 0; i < numAbilities; ++i) { int index = FindAbilityIndex(i+1, player); if (index != -1) { WriteInteger(fWrite, index); WriteInteger(fWrite, player->myskills.abilities[index].level); WriteInteger(fWrite, player->myskills.abilities[index].max_level); WriteInteger(fWrite, player->myskills.abilities[index].hard_max); WriteInteger(fWrite, player->myskills.abilities[index].modifier); WriteInteger(fWrite, (int)player->myskills.abilities[index].disable); WriteInteger(fWrite, (int)player->myskills.abilities[index].general_skill); } } //end abilities //begin weapons WriteInteger(fWrite, numWeapons); for (i = 0; i < numWeapons; ++i) { int index = FindWeaponIndex(i+1, player); if (index != -1) { int j; WriteInteger(fWrite, index); WriteInteger(fWrite, player->myskills.weapons[index].disable); for (j = 0; j < MAX_WEAPONMODS; ++j) { WriteInteger(fWrite, player->myskills.weapons[index].mods[j].level); WriteInteger(fWrite, player->myskills.weapons[index].mods[j].soft_max); WriteInteger(fWrite, player->myskills.weapons[index].mods[j].hard_max); } } } //end weapons //begin runes WriteInteger(fWrite, numRunes); for (i = 0; i < numRunes; ++i) { int index = FindRuneIndex(i+1, player); if (index != -1) { int j; WriteInteger(fWrite, index); WriteInteger(fWrite, player->myskills.items[index].itemtype); WriteInteger(fWrite, player->myskills.items[index].itemLevel); WriteInteger(fWrite, player->myskills.items[index].quantity); WriteInteger(fWrite, player->myskills.items[index].untradeable); WriteString(fWrite, player->myskills.items[index].id); WriteString(fWrite, player->myskills.items[index].name); WriteInteger(fWrite, player->myskills.items[index].numMods); WriteInteger(fWrite, player->myskills.items[index].setCode); WriteInteger(fWrite, player->myskills.items[index].classNum); for (j = 0; j < MAX_VRXITEMMODS; ++j) { WriteInteger(fWrite, player->myskills.items[index].modifiers[j].type); WriteInteger(fWrite, player->myskills.items[index].modifiers[j].index); WriteInteger(fWrite, player->myskills.items[index].modifiers[j].value); WriteInteger(fWrite, player->myskills.items[index].modifiers[j].set); } } } //end runes //***************************** //standard stats //***************************** //Exp WriteLong(fWrite, player->myskills.experience); //next_level WriteLong(fWrite, player->myskills.next_level); //Level WriteInteger(fWrite, player->myskills.level); //Class number WriteInteger(fWrite, player->myskills.class_num); //skill points WriteInteger(fWrite, player->myskills.speciality_points); //credits WriteInteger(fWrite, player->myskills.credits); //weapon points WriteInteger(fWrite, player->myskills.weapon_points); //respawn weapon WriteInteger(fWrite, player->myskills.respawn_weapon); //talent points WriteInteger(fWrite, player->myskills.talents.talentPoints); //***************************** //in-game stats //***************************** //respawns WriteInteger(fWrite, player->myskills.respawns); //health WriteInteger(fWrite, player->myskills.current_health); //max health WriteInteger(fWrite, MAX_HEALTH(player)); //armour WriteInteger(fWrite, player->client->pers.inventory[body_armor_index]); //max armour WriteInteger(fWrite, MAX_ARMOR(player)); //nerfme (cursing a player maybe?) WriteInteger(fWrite, player->myskills.nerfme); //***************************** //flags //***************************** //admin flag WriteInteger(fWrite, player->myskills.administrator); //boss flag WriteInteger(fWrite, player->myskills.boss); //***************************** //stats //***************************** //shots fired WriteInteger(fWrite, player->myskills.shots); //shots hit WriteInteger(fWrite, player->myskills.shots_hit); //frags WriteInteger(fWrite, player->myskills.frags); //deaths WriteInteger(fWrite, player->myskills.fragged); //number of sprees WriteInteger(fWrite, player->myskills.num_sprees); //max spree WriteInteger(fWrite, player->myskills.max_streak); //number of wars WriteInteger(fWrite, player->myskills.spree_wars); //number of sprees broken WriteInteger(fWrite, player->myskills.break_sprees); //number of wars broken WriteInteger(fWrite, player->myskills.break_spree_wars); //suicides WriteInteger(fWrite, player->myskills.suicides); //teleports (link this to "use tball self" maybe?) WriteInteger(fWrite, player->myskills.teleports); //number of 2fers WriteInteger(fWrite, player->myskills.num_2fers); //CTF statistics WriteInteger(fWrite, player->myskills.flag_pickups); WriteInteger(fWrite, player->myskills.flag_captures); WriteInteger(fWrite, player->myskills.flag_returns); WriteInteger(fWrite, player->myskills.flag_kills); WriteInteger(fWrite, player->myskills.offense_kills); WriteInteger(fWrite, player->myskills.defense_kills); WriteInteger(fWrite, player->myskills.assists); //End CTF //Don't let the player have > max cubes if (player->client->pers.inventory[power_cube_index] > player->client->pers.max_powercubes) player->client->pers.inventory[power_cube_index] = player->client->pers.max_powercubes; //standard iD inventory fwrite(player->client->pers.inventory, sizeof(int), MAX_ITEMS, fWrite); }
//*********************************************************************** // Load player v 1.0 //*********************************************************************** qboolean ReadPlayer_v1(FILE * fRead, edict_t *player) { int numAbilities, numWeapons, numRunes; int i; //player's title ReadString(player->myskills.title, fRead); //player's in-game name ReadString(player->myskills.player_name, fRead); //password ReadString(player->myskills.password, fRead); //email address ReadString(player->myskills.email, fRead); //owner ReadString(player->myskills.owner, fRead); //creation date ReadString(player->myskills.member_since, fRead); //last played date ReadString(player->myskills.last_played, fRead); //playing time total player->myskills.total_playtime = ReadInteger(fRead); //playing time today player->myskills.playingtime = ReadInteger(fRead); //begin talents player->myskills.talents.count = ReadInteger(fRead); for (i = 0; i < player->myskills.talents.count; ++i) { //don't crash. if (i > MAX_TALENTS) return false; player->myskills.talents.talent[i].id = ReadInteger(fRead); player->myskills.talents.talent[i].upgradeLevel = ReadInteger(fRead); player->myskills.talents.talent[i].maxLevel = ReadInteger(fRead); } //end talents //begin abilities numAbilities = ReadInteger(fRead); for (i = 0; i < numAbilities; ++i) { int index; index = ReadInteger(fRead); if ((index >= 0) && (index < MAX_ABILITIES)) { player->myskills.abilities[index].level = ReadInteger(fRead); player->myskills.abilities[index].max_level = ReadInteger(fRead); player->myskills.abilities[index].hard_max = ReadInteger(fRead); player->myskills.abilities[index].modifier = ReadInteger(fRead); player->myskills.abilities[index].disable = (qboolean)ReadInteger(fRead); player->myskills.abilities[index].general_skill = (qboolean)ReadInteger(fRead); } else { gi.dprintf("Error loading player: %s. Ability index not loaded correctly!\n", player->client->pers.netname); WriteToLogfile(player, "ERROR during loading: Ability index not loaded correctly!"); return false; } } //end abilities //begin weapons numWeapons = ReadInteger(fRead); for (i = 0; i < numWeapons; ++i) { int index; index = ReadInteger(fRead); if ((index >= 0 ) && (index < MAX_WEAPONS)) { int j; player->myskills.weapons[index].disable = ReadInteger(fRead); for (j = 0; j < MAX_WEAPONMODS; ++j) { player->myskills.weapons[index].mods[j].level = ReadInteger(fRead); player->myskills.weapons[index].mods[j].soft_max = ReadInteger(fRead); player->myskills.weapons[index].mods[j].hard_max = ReadInteger(fRead); } } else { gi.dprintf("Error loading player: %s. Weapon index not loaded correctly!\n", player->myskills.player_name); WriteToLogfile(player, "ERROR during loading: Weapon index not loaded correctly!"); return false; } } //end weapons //begin runes numRunes = ReadInteger(fRead); for (i = 0; i < numRunes; ++i) { int index; index = ReadInteger(fRead); if ((index >= 0) && (index < MAX_VRXITEMS)) { int j; player->myskills.items[index].itemtype = ReadInteger(fRead); player->myskills.items[index].itemLevel = ReadInteger(fRead); player->myskills.items[index].quantity = ReadInteger(fRead); player->myskills.items[index].untradeable = ReadInteger(fRead); ReadString(player->myskills.items[index].id, fRead); ReadString(player->myskills.items[index].name, fRead); player->myskills.items[index].numMods = ReadInteger(fRead); player->myskills.items[index].setCode = ReadInteger(fRead); player->myskills.items[index].classNum = ReadInteger(fRead); for (j = 0; j < MAX_VRXITEMMODS; ++j) { player->myskills.items[index].modifiers[j].type = ReadInteger(fRead); player->myskills.items[index].modifiers[j].index = ReadInteger(fRead); player->myskills.items[index].modifiers[j].value = ReadInteger(fRead); player->myskills.items[index].modifiers[j].set = ReadInteger(fRead); } } } //end runes //***************************** //standard stats //***************************** //Exp player->myskills.experience = ReadLong(fRead); //next_level player->myskills.next_level = ReadLong(fRead); //Level player->myskills.level = ReadInteger(fRead); //Class number player->myskills.class_num = ReadInteger(fRead); //skill points player->myskills.speciality_points = ReadInteger(fRead); //credits player->myskills.credits = ReadInteger(fRead); //weapon points player->myskills.weapon_points = ReadInteger(fRead); //respawn weapon player->myskills.respawn_weapon = ReadInteger(fRead); //talent points player->myskills.talents.talentPoints = ReadInteger(fRead); //***************************** //in-game stats //***************************** //respawns player->myskills.respawns = ReadInteger(fRead); //health player->myskills.current_health = ReadInteger(fRead); //max health player->myskills.max_health = ReadInteger(fRead); //armour player->myskills.current_armor = ReadInteger(fRead); //max armour player->myskills.max_armor = ReadInteger(fRead); //nerfme (cursing a player maybe?) player->myskills.nerfme = ReadInteger(fRead); //***************************** //flags //***************************** //admin flag player->myskills.administrator = ReadInteger(fRead); //boss flag player->myskills.boss = ReadInteger(fRead); //***************************** //stats //***************************** //shots fired player->myskills.shots = ReadInteger(fRead); //shots hit player->myskills.shots_hit = ReadInteger(fRead); //frags player->myskills.frags = ReadInteger(fRead); //deaths player->myskills.fragged = ReadInteger(fRead); //number of sprees player->myskills.num_sprees = ReadInteger(fRead); //max spree player->myskills.max_streak = ReadInteger(fRead); //number of wars player->myskills.spree_wars = ReadInteger(fRead); //number of sprees broken player->myskills.break_sprees = ReadInteger(fRead); //number of wars broken player->myskills.break_spree_wars = ReadInteger(fRead); //suicides player->myskills.suicides = ReadInteger(fRead); //teleports (link this to "use tballself" maybe?) player->myskills.teleports = ReadInteger(fRead); //number of 2fers player->myskills.num_2fers = ReadInteger(fRead); //CTF statistics player->myskills.flag_pickups = ReadInteger(fRead); player->myskills.flag_captures = ReadInteger(fRead); player->myskills.flag_returns = ReadInteger(fRead); player->myskills.flag_kills = ReadInteger(fRead); player->myskills.offense_kills = ReadInteger(fRead); player->myskills.defense_kills = ReadInteger(fRead); player->myskills.assists = ReadInteger(fRead); //End CTF //standard iD inventory fread(player->myskills.inventory, sizeof(int), MAX_ITEMS, fRead); //Apply runes V_ResetAllStats(player); for (i = 0; i < 3; ++i) V_ApplyRune(player, &player->myskills.items[i]); //Apply health if (player->myskills.current_health > MAX_HEALTH(player)) player->myskills.current_health = MAX_HEALTH(player); //Apply armor if (player->myskills.current_armor > MAX_ARMOR(player)) player->myskills.current_armor = MAX_ARMOR(player); player->myskills.inventory[body_armor_index] = player->myskills.current_armor; //done return true; }
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); }
float ArmorLevel (edict_t *ent) { return ((float)ent->client->pers.inventory[body_armor_index]/MAX_ARMOR(ent)); }
qboolean NeedArmor (edict_t *player) { return (player->client->pers.inventory[body_armor_index] < MAX_ARMOR(player)); }
qboolean VSFU_LoadPlayer(edict_t *player) { sqlite3_stmt* statement, *statement_mods; char* format; int numAbilities, numWeapons, numRunes; int i, r, id; V_VSFU_StartConn(); id = VSFU_GetID(player->client->pers.netname); if (id == -1) return false; LQUERY(va("SELECT * FROM userdata WHERE char_idx=%d", id)); strcpy(player->myskills.title, sqlite3_column_text(statement, 1)); strcpy(player->myskills.player_name, sqlite3_column_text(statement, 2)); strcpy(player->myskills.password, sqlite3_column_text(statement, 3)); strcpy(player->myskills.email, sqlite3_column_text(statement, 4)); strcpy(player->myskills.owner, sqlite3_column_text(statement, 5)); strcpy(player->myskills.member_since, sqlite3_column_text(statement, 6)); strcpy(player->myskills.last_played, sqlite3_column_text(statement, 7)); player->myskills.total_playtime = sqlite3_column_int(statement, 8); player->myskills.playingtime = sqlite3_column_int(statement, 9); sqlite3_finalize(statement); format = va("SELECT COUNT(*) FROM talents WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); //begin talents player->myskills.talents.count = sqlite3_column_int(statement, 0); sqlite3_finalize(statement); format = va("SELECT * FROM talents WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); for (i = 0; i < player->myskills.talents.count; ++i) { //don't crash. if (i > MAX_TALENTS) return false; player->myskills.talents.talent[i].id = sqlite3_column_int(statement, 1); player->myskills.talents.talent[i].upgradeLevel = sqlite3_column_int(statement, 2); player->myskills.talents.talent[i].maxLevel = sqlite3_column_int(statement, 3); if ( (r = sqlite3_step(statement)) == SQLITE_DONE) break; } //end talents sqlite3_finalize(statement); format = va("SELECT COUNT(*) FROM abilities WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); //begin abilities numAbilities = sqlite3_column_int(statement, 0); sqlite3_finalize(statement); format = va("SELECT * FROM abilities WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); for (i = 0; i < numAbilities; ++i) { int index; index = sqlite3_column_int(statement, 1); if ((index >= 0) && (index < MAX_ABILITIES)) { player->myskills.abilities[index].level = sqlite3_column_int(statement, 2); player->myskills.abilities[index].max_level = sqlite3_column_int(statement, 3); player->myskills.abilities[index].hard_max = sqlite3_column_int(statement, 4); player->myskills.abilities[index].modifier = sqlite3_column_int(statement, 5); player->myskills.abilities[index].disable = sqlite3_column_int(statement, 6); player->myskills.abilities[index].general_skill = (qboolean)sqlite3_column_int(statement, 7); if ( (r = sqlite3_step(statement)) == SQLITE_DONE) break; } else { gi.dprintf("Error loading player: %s. Ability index not loaded correctly!\n", player->client->pers.netname); vrx_write_to_logfile(player, "ERROR during loading: Ability index not loaded correctly!"); return false; } } //end abilities sqlite3_finalize(statement); format = va("SELECT COUNT(*) FROM weapon_meta WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); //begin weapons numWeapons = sqlite3_column_int(statement, 0); sqlite3_finalize(statement); format = va("SELECT * FROM weapon_meta WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); for (i = 0; i < numWeapons; ++i) { int index; index = sqlite3_column_int(statement, 1); if ((index >= 0 ) && (index < MAX_WEAPONS)) { int j; player->myskills.weapons[index].disable = sqlite3_column_int(statement, 2); format = strdup(va("SELECT * FROM weapon_mods WHERE weapon_index=%d AND char_idx=%d", index, id)); r = sqlite3_prepare_v2(db, format, strlen(format), &statement_mods, NULL); r = sqlite3_step(statement_mods); for (j = 0; j < MAX_WEAPONMODS; ++j) { player->myskills.weapons[index].mods[j].level = sqlite3_column_int(statement_mods, 3); player->myskills.weapons[index].mods[j].soft_max = sqlite3_column_int(statement_mods, 4); player->myskills.weapons[index].mods[j].hard_max = sqlite3_column_int(statement_mods, 5); if ((r = sqlite3_step(statement_mods)) == SQLITE_DONE) break; } free (format); sqlite3_finalize(statement_mods); } else { gi.dprintf("Error loading player: %s. Weapon index not loaded correctly!\n", player->myskills.player_name); vrx_write_to_logfile(player, "ERROR during loading: Weapon index not loaded correctly!"); return false; } if ((r = sqlite3_step(statement)) == SQLITE_DONE) break; } sqlite3_finalize(statement); //end weapons //begin runes format = va("SELECT COUNT(*) FROM runes_meta WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); numRunes = sqlite3_column_int(statement, 0); sqlite3_finalize(statement); format = va("SELECT * FROM runes_meta WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); for (i = 0; i < numRunes; ++i) { int index; index = sqlite3_column_int(statement, 1); if ((index >= 0) && (index < MAX_VRXITEMS)) { int j; player->myskills.items[index].itemtype = sqlite3_column_int(statement, 2); player->myskills.items[index].itemLevel = sqlite3_column_int(statement, 3); player->myskills.items[index].quantity = sqlite3_column_int(statement, 4); player->myskills.items[index].untradeable = sqlite3_column_int(statement, 5); strcpy(player->myskills.items[index].id, sqlite3_column_text(statement, 6)); strcpy(player->myskills.items[index].name, sqlite3_column_text(statement, 7)); player->myskills.items[index].numMods = sqlite3_column_int(statement, 8); player->myskills.items[index].setCode = sqlite3_column_int(statement, 9); player->myskills.items[index].classNum = sqlite3_column_int(statement, 10); format = strdup(va("SELECT * FROM runes_mods WHERE rune_index=%d AND char_idx=%d", index, id)); r = sqlite3_prepare_v2(db, format, strlen(format), &statement_mods, NULL); r = sqlite3_step(statement_mods); for (j = 0; j < MAX_VRXITEMMODS; ++j) { if (Lua_GetIntVariable("useMysqlTablesOnSQLite", 0)) { player->myskills.items[index].modifiers[j].type = sqlite3_column_int(statement_mods, 3); player->myskills.items[index].modifiers[j].index = sqlite3_column_int(statement_mods, 4); player->myskills.items[index].modifiers[j].value = sqlite3_column_int(statement_mods, 5); player->myskills.items[index].modifiers[j].set = sqlite3_column_int(statement_mods, 6); }else { player->myskills.items[index].modifiers[j].type = sqlite3_column_int(statement_mods, 2); player->myskills.items[index].modifiers[j].index = sqlite3_column_int(statement_mods, 3); player->myskills.items[index].modifiers[j].value = sqlite3_column_int(statement_mods, 4); player->myskills.items[index].modifiers[j].set = sqlite3_column_int(statement_mods, 5); } if ((r = sqlite3_step(statement_mods)) == SQLITE_DONE) break; } free (format); sqlite3_finalize(statement_mods); } if ((r = sqlite3_step(statement)) == SQLITE_DONE) break; } sqlite3_finalize(statement); //end runes //***************************** //standard stats //***************************** format = va("SELECT * FROM point_data WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); //Exp player->myskills.experience = sqlite3_column_int(statement, 1); //next_level player->myskills.next_level = sqlite3_column_int(statement, 2); //Level player->myskills.level = sqlite3_column_int(statement, 3); //Class number player->myskills.class_num = sqlite3_column_int(statement, 4); //skill points player->myskills.speciality_points = sqlite3_column_int(statement, 5); //credits player->myskills.credits = sqlite3_column_int(statement, 6); //weapon points player->myskills.weapon_points = sqlite3_column_int(statement, 7); //respawn weapon player->myskills.respawn_weapon = sqlite3_column_int(statement, 8); //talent points player->myskills.talents.talentPoints = sqlite3_column_int(statement, 9); sqlite3_finalize(statement); format = va("SELECT * FROM character_data WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); //***************************** //in-game stats //***************************** //respawns player->myskills.weapon_respawns = sqlite3_column_int(statement, 1); //health player->myskills.current_health = sqlite3_column_int(statement, 2); //max health player->myskills.max_health = sqlite3_column_int(statement, 3); //armour player->myskills.current_armor = sqlite3_column_int(statement, 4); //max armour player->myskills.max_armor = sqlite3_column_int(statement, 5); //nerfme (cursing a player maybe?) player->myskills.nerfme = sqlite3_column_int(statement, 6); //***************************** //flags //***************************** //admin flag player->myskills.administrator = sqlite3_column_int(statement, 7); //boss flag player->myskills.boss = sqlite3_column_int(statement, 8); //***************************** //stats //***************************** sqlite3_finalize(statement); format = va("SELECT * FROM game_stats WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); //shots fired player->myskills.shots = sqlite3_column_int(statement, 1); //shots hit player->myskills.shots_hit = sqlite3_column_int(statement, 2); //frags player->myskills.frags = sqlite3_column_int(statement, 3); //deaths player->myskills.fragged = sqlite3_column_int(statement, 4); //number of sprees player->myskills.num_sprees = sqlite3_column_int(statement, 5); //max spree player->myskills.max_streak = sqlite3_column_int(statement, 6); //number of wars player->myskills.spree_wars = sqlite3_column_int(statement, 7); //number of sprees broken player->myskills.break_sprees = sqlite3_column_int(statement, 8); //number of wars broken player->myskills.break_spree_wars = sqlite3_column_int(statement, 9); //suicides player->myskills.suicides = sqlite3_column_int(statement, 10); //teleports (link this to "use tballself" maybe?) player->myskills.teleports = sqlite3_column_int(statement, 11); //number of 2fers player->myskills.num_2fers = sqlite3_column_int(statement, 12); sqlite3_finalize(statement); format = va("SELECT * FROM ctf_stats WHERE char_idx=%d", id); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); r = sqlite3_step(statement); //CTF statistics player->myskills.flag_pickups = sqlite3_column_int(statement, 1); player->myskills.flag_captures = sqlite3_column_int(statement, 2); player->myskills.flag_returns = sqlite3_column_int(statement, 3); player->myskills.flag_kills = sqlite3_column_int(statement, 4); player->myskills.offense_kills = sqlite3_column_int(statement, 5); player->myskills.defense_kills = sqlite3_column_int(statement, 6); player->myskills.assists = sqlite3_column_int(statement, 7); //End CTF sqlite3_finalize(statement); //Apply runes V_ResetAllStats(player); for (i = 0; i < 4; ++i) V_ApplyRune(player, &player->myskills.items[i]); //Apply health if (player->myskills.current_health > MAX_HEALTH(player)) player->myskills.current_health = MAX_HEALTH(player); //Apply armor if (player->myskills.current_armor > MAX_ARMOR(player)) player->myskills.current_armor = MAX_ARMOR(player); player->myskills.inventory[body_armor_index] = player->myskills.current_armor; V_VSFU_Cleanup(); return true; }
//************************************************ //************************************************ void VSFU_SavePlayer(edict_t *player) { sqlite3_stmt *statement; int r, i, id; int numAbilities = CountAbilities(player); int numWeapons = CountWeapons(player); int numRunes = CountRunes(player); char *format; V_VSFU_StartConn(); id = VSFU_GetID(player->client->pers.netname); BeginTransaction(db); if (id == -1) { // Create initial database. id = VSFU_NewID(); gi.dprintf("SQLite (single mode): creating initial data for player id %d..", id); if (!Lua_GetIntVariable("useMysqlTablesOnSQLite", 0)) { /* sorry about this :( -az*/ QUERY(va (CA, id)); QUERY(va (CB, id)); QUERY(va (CC, id)); QUERY(va (CD, id)); QUERY(va (CE, id)); }else { QUERY(va (CA, id)); QUERY(va (CB, id)); QUERY(va (CC, id)); QUERY(va (CD, id)); QUERY(va("INSERT INTO userdata VALUES (%d,\"\",\"\",\"\",\"\",\"\",\"\",\"\",0,0,0)", id)); } gi.dprintf("inserted bases.\n", r); } { // real saving sqlite3_stmt *statement; // reset tables (remove records for reinsertion) for (i = 0; i < TOTAL_RESETTABLES; i++) { QUERY( va(VSFU_RESETTABLES[i], id) ); } QUERY(strdup(va(VSFU_UPDATEUDATA, player->myskills.title, player->client->pers.netname, player->myskills.password, player->myskills.email, player->myskills.owner, player->myskills.member_since, player->myskills.last_played, player->myskills.total_playtime, player->myskills.playingtime, id))); free (format); // talents for (i = 0; i < player->myskills.talents.count; ++i) { QUERY( strdup(va(VSFU_INSERTTALENT, id, player->myskills.talents.talent[i].id, player->myskills.talents.talent[i].upgradeLevel, player->myskills.talents.talent[i].maxLevel)) ); free (format); } // abilities for (i = 0; i < numAbilities; ++i) { int index = FindAbilityIndex(i+1, player); if (index != -1) { format = strdup(va(VSFU_INSERTABILITY, id, index, player->myskills.abilities[index].level, player->myskills.abilities[index].max_level, player->myskills.abilities[index].hard_max, player->myskills.abilities[index].modifier, (int)player->myskills.abilities[index].disable, (int)player->myskills.abilities[index].general_skill)); r = sqlite3_prepare_v2(db, format, strlen(format), &statement, NULL); // insert ability r = sqlite3_step(statement); sqlite3_finalize(statement); free (format); // this will be slow... } } // gi.dprintf("saved abilities"); //***************************** //in-game stats //***************************** QUERY(strdup(va(VSFU_UPDATECDATA, player->myskills.weapon_respawns, player->myskills.current_health, MAX_HEALTH(player), player->client->pers.inventory[body_armor_index], MAX_ARMOR(player), player->myskills.nerfme, player->myskills.administrator, // flags player->myskills.boss, id))); free (format); //***************************** //stats //***************************** QUERY( strdup(va(VSFU_UPDATESTATS, player->myskills.shots, player->myskills.shots_hit, player->myskills.frags, player->myskills.fragged, player->myskills.num_sprees, player->myskills.max_streak, player->myskills.spree_wars, player->myskills.break_sprees, player->myskills.break_spree_wars, player->myskills.suicides, player->myskills.teleports, player->myskills.num_2fers, id)) ); free (format); //***************************** //standard stats //***************************** QUERY( strdup(va(VSFU_UPDATEPDATA, player->myskills.experience, player->myskills.next_level, player->myskills.level, player->myskills.class_num, player->myskills.speciality_points, player->myskills.credits, player->myskills.weapon_points, player->myskills.respawn_weapon, player->myskills.talents.talentPoints, id)) ); free (format); //begin weapons for (i = 0; i < numWeapons; ++i) { int index = FindWeaponIndex(i+1, player); if (index != -1) { int j; QUERY( strdup(va(VSFU_INSERTWMETA, id, index, player->myskills.weapons[index].disable))); free (format); for (j = 0; j < MAX_WEAPONMODS; ++j) { QUERY( strdup(va(VSFU_INSERTWMOD, id, index, j, player->myskills.weapons[index].mods[j].level, player->myskills.weapons[index].mods[j].soft_max, player->myskills.weapons[index].mods[j].hard_max)) ); free (format); } } } //end weapons //begin runes for (i = 0; i < numRunes; ++i) { int index = FindRuneIndex(i+1, player); if (index != -1) { int j; QUERY( strdup(va(VSFU_INSERTRMETA, id, index, player->myskills.items[index].itemtype, player->myskills.items[index].itemLevel, player->myskills.items[index].quantity, player->myskills.items[index].untradeable, player->myskills.items[index].id, player->myskills.items[index].name, player->myskills.items[index].numMods, player->myskills.items[index].setCode, player->myskills.items[index].classNum))); free (format); for (j = 0; j < MAX_VRXITEMMODS; ++j) { char* query; // cant remove columns with sqlite. // ugly hack to work around that if (Lua_GetIntVariable("useMysqlTablesOnSQLite", 0)) query = VSFU_INSERTRMODEX; else query = VSFU_INSERTRMOD; QUERY( strdup(va(query, id, index, player->myskills.items[index].modifiers[j].type, player->myskills.items[index].modifiers[j].index, player->myskills.items[index].modifiers[j].value, player->myskills.items[index].modifiers[j].set)) ); free (format); } } } //end runes QUERY( strdup(va(VSFU_UPDATECTFSTATS, player->myskills.flag_pickups, player->myskills.flag_captures, player->myskills.flag_returns, player->myskills.flag_kills, player->myskills.offense_kills, player->myskills.defense_kills, player->myskills.assists, id)) ); free (format); } // end saving CommitTransaction(db); if (player->client->pers.inventory[power_cube_index] > player->client->pers.max_powercubes) player->client->pers.inventory[power_cube_index] = player->client->pers.max_powercubes; V_VSFU_Cleanup(); }
void NatureTotem_think(edict_t *self, edict_t *caster) { edict_t *target = NULL; qboolean isSomeoneHealed = false; float cdmult = 1.0; //Find players in radius and attack them. while ((target = findradius(target, self->s.origin, TOTEM_MAX_RANGE)) != NULL) { if (G_ValidAlliedTarget(self, target, true)) { int maxHP;// = MAX_HEALTH(target); int maxArmor;// = MAX_ARMOR(target); int maxcubes;// = target->client->pers.max_powercubes; int *armor;// = &target->client->pers.inventory[body_armor_index]; int *cubes;// = &target->client->pers.inventory[ITEM_INDEX(Fdi_POWERCUBE)]; int regen_frames;//4.2 regen for non-clients if (!target->client) { regen_frames = 1000 / self->monsterinfo.level; // full-regeneration in 15 seconds at level 10 M_Regenerate(target, regen_frames, 50, 1.0, true, true, false, &target->monsterinfo.regen_delay2); continue; } maxHP = MAX_HEALTH(target); maxArmor = MAX_ARMOR(target); maxcubes = target->client->pers.max_powercubes; armor = &target->client->pers.inventory[body_armor_index]; cubes = &target->client->pers.inventory[ITEM_INDEX(Fdi_POWERCUBE)]; //Heal their health. if(target->health < maxHP) { target->health += NATURETOTEM_HEALTH_BASE + self->monsterinfo.level * NATURETOTEM_HEALTH_MULT; if(target->health > maxHP) target->health = maxHP; isSomeoneHealed = true; } //Heal their armor. if(*armor < maxArmor) { *armor += NATURETOTEM_ARMOR_BASE + self->monsterinfo.level * NATURETOTEM_ARMOR_MULT; if(*armor > maxArmor) *armor = maxArmor; isSomeoneHealed = true; } //Talent: Peace. if(*cubes < maxcubes) { //Give them 5 cubes per talent point. *cubes += getTalentLevel(caster, TALENT_PEACE) * 10; if(*cubes > maxcubes) *cubes = maxcubes; isSomeoneHealed = true; } // We remove curses. -az CurseRemove(target, 0); } } //Play a sound or something. if(isSomeoneHealed) { gi.sound(self, CHAN_ITEM, gi.soundindex("items/n_health.wav"), 1, ATTN_NORM, 0); } cdmult = level.time + NATURETOTEM_REFIRE_BASE + NATURETOTEM_REFIRE_MULT * self->monsterinfo.level; if (cdmult <= level.time) cdmult = level.time + 0.1; //Next think. self->delay = cdmult; }
void Healing_think(edict_t *self) { //Find my slot que_t *slot = NULL; int heal_amount = HEALING_HEAL_BASE + HEALING_HEAL_BONUS * self->owner->myskills.abilities[HEALING].current_level; float cooldown = 1.0; slot = que_findtype(self->enemy->curses, NULL, HEALING); // Blessing self-terminates if the enemy dies or the duration expires if (!slot || !que_valident(slot)) { que_removeent(self->enemy->curses, self, true); return; } //Stick with the target VectorCopy(self->enemy->s.origin, self->s.origin); gi.linkentity(self); //Next think time self->nextthink = level.time + cooldown; //Heal the target's armor if (!self->enemy->client) { //Check to make sure it's a monster if (!self->enemy->mtype) return; heal_amount = self->enemy->max_health * (0.01 * self->owner->myskills.abilities[HEALING].current_level); // 1% healed per level if (heal_amount > 100) heal_amount = 100; //Heal the momster's health self->enemy->health += heal_amount; if (self->enemy->health > self->enemy->max_health) self->enemy->health = self->enemy->max_health; if (self->enemy->monsterinfo.power_armor_type) { heal_amount = self->enemy->monsterinfo.power_armor_power * (0.01 * self->owner->myskills.abilities[HEALING].current_level); // 1% healed per level if (heal_amount > 100) heal_amount = 100; //Heal the monster's armor self->enemy->monsterinfo.power_armor_power += heal_amount; if (self->enemy->monsterinfo.power_armor_power > self->enemy->monsterinfo.max_armor) self->enemy->monsterinfo.power_armor_power = self->enemy->monsterinfo.max_armor; } } else { if (self->enemy->health < MAX_HEALTH(self->enemy)) { //Heal health self->enemy->health += heal_amount; if (self->enemy->health > MAX_HEALTH(self->enemy)) self->enemy->health = MAX_HEALTH(self->enemy); } if (self->enemy->client->pers.inventory[body_armor_index] < MAX_ARMOR(self->enemy)) { //Heal armor heal_amount *= 0.5; // don't heal as much armor if (heal_amount < 1) heal_amount = 1; self->enemy->client->pers.inventory[body_armor_index] += heal_amount; if (self->enemy->client->pers.inventory[body_armor_index] > MAX_ARMOR(self->enemy)) self->enemy->client->pers.inventory[body_armor_index] = MAX_ARMOR(self->enemy); } } }