Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void NPC::Killed(Character *from, int amount, int spell_id)
- {
- double droprate = this->map->world->config["DropRate"];
- double exprate = this->map->world->config["ExpRate"];
- int sharemode = this->map->world->config["ShareMode"];
- int partysharemode = this->map->world->config["PartyShareMode"];
- int dropratemode = this->map->world->config["DropRateMode"];
- std::set<Party *> parties;
- int most_damage_counter = 0;
- Character *most_damage = nullptr;
- NPC_Drop *drop = nullptr;
- this->alive = false;
- this->dead_since = int(Timer::GetTime());
- if (dropratemode == 1)
- {
- std::vector<NPC_Drop *> drops;
- UTIL_FOREACH_CREF(this->Data().drops, checkdrop)
- {
- if (util::rand(0.0, 100.0) <= checkdrop->chance * droprate)
- {
- drops.push_back(checkdrop.get());
- }
- }
- if (drops.size() > 0)
- {
- drop = drops[util::rand(0, drops.size()-1)];
- }
- }
- else if (dropratemode == 2)
- {
- UTIL_FOREACH_CREF(this->Data().drops, checkdrop)
- {
- if (util::rand(0.0, 100.0) <= checkdrop->chance * droprate)
- {
- drop = checkdrop.get();
- break;
- }
- }
- }
- else if (dropratemode == 3)
- {
- double roll = util::rand(0.0, this->Data().drops_chance_total);
- UTIL_FOREACH_CREF(this->Data().drops, checkdrop)
- {
- if (roll >= checkdrop->chance_offset && roll < checkdrop->chance_offset+checkdrop->chance)
- {
- drop = checkdrop.get();
- break;
- }
- }
- }
- if (sharemode == 1)
- {
- UTIL_FOREACH_CREF(this->damagelist, opponent)
- {
- if (opponent->damage > most_damage_counter)
- {
- most_damage_counter = opponent->damage;
- most_damage = opponent->attacker;
- }
- }
- }
- int dropuid = 0;
- int dropid = 0;
- int dropamount = 0;
- Character* drop_winner = from;
- if (drop)
- {
- dropuid = this->map->GenerateItemID();
- dropid = drop->id;
- dropamount = util::rand(drop->min, drop->max);
- // Selects a random number between 0 and maxhp, and decides the winner based on that
- switch (sharemode)
- {
- case 0:
- drop_winner = from;
- break;
- case 1:
- drop_winner = most_damage;
- break;
- case 2:
- {
- int rewarded_hp = util::rand(0, this->totaldamage - 1);
- int count_hp = 0;
- UTIL_FOREACH_CREF(this->damagelist, opponent)
- {
- if (opponent->attacker->InRange(this))
- {
- if (rewarded_hp >= count_hp && rewarded_hp < opponent->damage)
- {
- drop_winner = opponent->attacker;
- break;
- }
- count_hp += opponent->damage;
- }
- }
- }
- break;
- case 3:
- {
- int rand = util::rand(0, this->damagelist.size() - 1);
- int i = 0;
- UTIL_FOREACH_CREF(this->damagelist, opponent)
- {
- if (opponent->attacker->InRange(this))
- {
- if (rand == i++)
- {
- drop_winner = opponent->attacker;
- break;
- }
- }
- }
- }
- break;
- }
- int accessory = drop_winner->paperdoll[Character::Accessory];
- int auto_gold_accessory = this->map->world->accesory_config["GoldPickupId"];
- bool do_auto_gold = (accessory > 0
- && accessory == auto_gold_accessory);
- if (do_auto_gold && drop->id == 1)
- {
- if (drop_winner->AddItem(dropid, dropamount))
- {
- PacketBuilder reply(PACKET_ITEM, PACKET_GET);
- reply.AddShort(0);
- reply.AddShort(dropid);
- reply.AddThree(dropamount);
- reply.AddChar(from->weight);
- reply.AddChar(from->maxweight);
- drop_winner->Send(reply);
- }
- dropuid = 0;
- dropid = 0;
- dropamount = 0;
- }
- else
- {
- std::shared_ptr<Map_Item> newitem(std::make_shared<Map_Item>(dropuid, dropid, dropamount, this->x, this->y, drop_winner->PlayerID(), Timer::GetTime() + static_cast<int>(this->map->world->config["ProtectNPCDrop"])));
- this->map->items.push_back(newitem);
- }
- }
- UTIL_FOREACH(this->map->characters, character)
- {
- std::list<std::unique_ptr<NPC_Opponent>>::iterator findopp = this->damagelist.begin();
- for (; findopp != this->damagelist.end() && (*findopp)->attacker != character; ++findopp); // no loop body
- if (findopp != this->damagelist.end() || character->InRange(this))
- {
- bool level_up = false;
- PacketBuilder builder(spell_id == -1 ? PACKET_NPC : PACKET_CAST, PACKET_SPEC, 26);
- if (this->ENF().exp != 0)
- {
- if (findopp != this->damagelist.end())
- {
- int reward;
- switch (sharemode)
- {
- case 0:
- if (character == from)
- {
- reward = int(std::ceil(double(this->ENF().exp) * exprate));
- if (reward > 0)
- {
- if (partysharemode)
- {
- if (character->party)
- {
- character->party->ShareEXP(reward, partysharemode, this->map);
- }
- else
- {
- character->exp += reward;
- }
- }
- else
- {
- character->exp += reward;
- }
- }
- }
- break;
- case 1:
- if (character == most_damage)
- {
- reward = int(std::ceil(double(this->ENF().exp) * exprate));
- if (reward > 0)
- {
- if (partysharemode)
- {
- if (character->party)
- {
- character->party->ShareEXP(reward, partysharemode, this->map);
- }
- else
- {
- character->exp += reward;
- }
- }
- else
- {
- character->exp += reward;
- }
- }
- }
- break;
- case 2:
- reward = int(std::ceil(double(this->ENF().exp) * exprate * (double((*findopp)->damage) / double(this->totaldamage))));
- if (reward > 0)
- {
- if (partysharemode)
- {
- if (character->party)
- {
- character->party->temp_expsum += reward;
- parties.insert(character->party);
- }
- else
- {
- character->exp += reward;
- }
- }
- else
- {
- character->exp += reward;
- }
- }
- break;
- case 3:
- reward = int(std::ceil(double(this->ENF().exp) * exprate * (double(this->damagelist.size()) / 1.0)));
- if (reward > 0)
- {
- if (partysharemode)
- {
- if (character->party)
- {
- character->party->temp_expsum += reward;
- }
- else
- {
- character->exp += reward;
- }
- }
- else
- {
- character->exp += reward;
- }
- }
- break;
- }
- character->exp = std::min(character->exp, static_cast<int>(this->map->world->config["MaxExp"]));
- while (character->level < static_cast<int>(this->map->world->config["MaxLevel"]) && character->exp >= this->map->world->exp_table[character->level+1])
- {
- level_up = true;
- ++character->level;
- character->statpoints += static_cast<int>(this->map->world->config["StatPerLevel"]);
- character->skillpoints += static_cast<int>(this->map->world->config["SkillPerLevel"]);
- character->CalculateStats();
- }
- if (level_up)
- {
- builder.SetID(spell_id == -1 ? PACKET_NPC : PACKET_CAST, PACKET_ACCEPT);
- builder.ReserveMore(33);
- }
- }
- }
- if (spell_id != -1)
- builder.AddShort(spell_id);
- builder.AddShort(drop_winner->PlayerID());
- builder.AddChar(drop_winner->direction);
- builder.AddShort(this->index);
- builder.AddShort(dropuid);
- builder.AddShort(dropid);
- builder.AddChar(this->x);
- builder.AddChar(this->y);
- builder.AddInt(dropamount);
- builder.AddThree(amount);
- if (spell_id != -1)
- builder.AddShort(from->tp);
- if ((sharemode == 0 && character == from) || (sharemode != 0 && findopp != this->damagelist.end()))
- {
- builder.AddInt(character->exp);
- }
- if (level_up)
- {
- builder.AddChar(character->level);
- builder.AddShort(character->statpoints);
- builder.AddShort(character->skillpoints);
- builder.AddShort(character->maxhp);
- builder.AddShort(character->maxtp);
- builder.AddShort(character->maxsp);
- }
- character->Send(builder);
- }
- }
- UTIL_FOREACH(parties, party)
- {
- party->ShareEXP(party->temp_expsum, partysharemode, this->map);
- party->temp_expsum = 0;
- }
- UTIL_FOREACH_CREF(this->damagelist, opponent)
- {
- opponent->attacker->unregister_npc.erase(
- std::remove(UTIL_RANGE(opponent->attacker->unregister_npc), this),
- opponent->attacker->unregister_npc.end()
- );
- }
- this->damagelist.clear();
- this->totaldamage = 0;
- short childid = -1;
- if (this->ENF().boss)
- {
- std::vector<NPC*> child_npcs;
- UTIL_FOREACH(this->map->npcs, npc)
- {
- if (npc->ENF().child && !npc->ENF().boss && npc->alive)
- {
- child_npcs.push_back(npc);
- }
- }
- UTIL_FOREACH(child_npcs, npc)
- {
- if (!npc->temporary && (childid == -1 || childid == npc->id))
- {
- npc->Die(false);
- childid = npc->id;
- }
- else
- {
- npc->Die(true);
- }
- }
- }
- if (childid != -1)
- {
- PacketBuilder builder(PACKET_NPC, PACKET_JUNK, 2);
- builder.AddShort(childid);
- UTIL_FOREACH(this->map->characters, character)
- {
- character->Send(builder);
- }
- }
- if (this->temporary)
- {
- this->map->npcs.erase(
- std::remove(this->map->npcs.begin(), this->map->npcs.end(), this),
- this->map->npcs.end()
- );
- }
- UTIL_FOREACH(from->quests, q)
- {
- if (!q.second || q.second->GetQuest()->Disabled())
- continue;
- q.second->KilledNPC(this->ENF().id);
- }
- if (this->temporary)
- {
- delete this;
- return;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement