Hello,
Since I'm pretty busy on my study, I'll never start a server..
So I'd like to share a couple of the codes I wrote.
The code is fearly readable and is royally filled with comments.
Please keep the credits to me, Jiggens.
Well let's get to the fun part.
This class, refers to the Diablo 2 identification system (Deckard Cain).
This is just the class to generate an item entry, it's up to you to extend it with your creativity in AI/Gossip scripts.
I can tell a whole feary about how to use and install it..
But the point is I keep it up to you, since you will have to understand the class to use it in your scripts.
Succes and Enyoy!
The class:
Pick.cpp
Code:
#include "Pick.h"
Pick::Pick() {};
// Deconstructor.
Pick::~Pick()
{
list<Item*>::iterator itr = List.begin();
for(; itr != List.end(); ++itr) { delete (*itr); }
}
void Pick::BuildList(bool b_level, uint32 num_level)
{
// Dereference to the struct: Item.
Item* record;
QueryResult* query;
Field* field;
// num will hold the addition of all chances in the table
float num;
// Query;
if(b_level)
{
// Select in range.
uint32 max = num_level +5;
uint32 min = num_level -5;
query = WorldDatabase.Query("SELECT * FROM unidentified WHERE level < %u AND level > %u AND entry != '0' AND chance != '0' ORDER BY chance ASC;", max, min);
}
else
query = WorldDatabase.Query("SELECT * FROM unidentified WHERE entry != '0' AND chance != '0' ORDER BY chance ASC;");
if(query)
{
// Get the addition of all chances in the table,
// with this value we can calculate the chance
// of the item being picked out the whole list.
// * Chance in percent(%): K/P
// K: <indivual chance of item>
// P: <addition of all chances in the table>
num = GetTotalChance(b_level, num_level);
do
{
field = query->Fetch();
record = new Item;
// Item entry.
record->entry = field[0].GetUInt32();
// The indivual chance on the item.
// This value ranges from 0 to 100.
float chance = field[1].GetFloat();
// Push the indivual chance.
record->indivual = chance;
// Chance in the list: (chance of item) / (total chance).
record->chance = (chance/num)*100.0f;
// Push the record back in the structs' vector.
List.push_back(record);
} while(query->NextRow());
}
};
float Pick::GetTotalChance(bool b_level, uint32 num_level)
{
// total will contain the total chance, this number will be returned in the function.
// But also we'll set the total_chance (member of Pick), to store it;
// this value might be needed later.
float total = 0.0f;
QueryResult* query;
Field* field;
// Query;
if(b_level)
{
// Select in a range.
uint32 max = num_level +5;
uint32 min = num_level -5;
query = WorldDatabase.Query("SELECT chance FROM unidentified WHERE level < %u AND level > %u AND entry != '0' AND chance != '0';", max, min);
}
else
query = WorldDatabase.Query("SELECT chance FROM unidentified WHERE entry != '0' AND chance != '0';");
if(query)
{
do
{
field = query->Fetch();
// Add the chance to the total chance.
total += field[0].GetFloat();
}
while(query->NextRow());
}
// Store the total chance.
total_chance = total;
// Return the total chance.
return total;
};
float Pick::Roll()
{
// Generate a random float.
float roll = ((float)rand()/(float)RAND_MAX)*100.0f;
// Return the random float
return roll;
};
uint32 Pick::GenerateId()
{
// This uint32 will be returned;
// containing the item entry generated.
uint32 item;
// Roll a random float.
float perc = Roll();
// This float we well be holding the
// left boundary of the chance distribution.
float chance = 0.0f;
// Our list where our entries and indivual
// chances are stored.
list<Item*>::iterator itr = List.begin();
// Let's iterate trough the list.
for(; itr != List.end(); ++itr)
{
// If chance > 0.0f it means this isn't the first record
// and we have a left boundary greater then 0.0f.
if(chance > 0.0f)
{
// We set the entry to the this record, if the generated
// random float is smaller then the right boundary
// and greater then the left boundary.
// - left boundary: <chance>
// - right boundary: <chance of the current record> + <chance>
// * <chance> -> see "float chance = 0.0f", it's
// basicly the chance of the previous item in the list.
if(perc < ((*itr)->chance + chance) && perc > chance)
{
// Assign the entry to our return value.
item = (*itr)->entry;
// Item is generated, we break the loop.
break;
}
}
// This is the first record in the list, left
// boundary is 0.0f.
else
{
// No left boundary comparison needed.
// first record, so we don't have to add
// our stored chance, if we do it, it won't
// chance anything; chance = 0.0f in this case.
if(perc < (*itr)->chance)
{
item = (*itr)->entry;
// Item id is generated, we break the loop.
break;
}
}
// Add the chance of the current record to our float, 'chance'.
chance += (*itr)->chance;
}
return item;
};
Pick.h
Code:
#include "StdAfx.h"
#pragma once
class Pick
{
public:
Pick();
~Pick();
struct Item
{
uint32 entry; // Item entry.
float indivual; // Percent(%), value ranges from 0 to 100.
float chance;
};
list<Item*> List;
float total_chance;
void BuildList(bool b_level, uint32 num_level);
float GetTotalChance(bool b_level, uint32 num_level);
float Roll();
uint32 GenerateId();
};
Sql:
Code:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `unidentified`
-- ----------------------------
DROP TABLE IF EXISTS `unidentified`;
CREATE TABLE `unidentified` (
`entry` int(11) NOT NULL,
`chance` float NOT NULL,
`level` int(11) NOT NULL,
PRIMARY KEY (`entry`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of unidentified
-- ----------------------------
Little example of how to generate an entry.
Code:
// entry = found item entry of unidentified item.
ItemPrototype* proto = ItemPrototypeStorage.LookupEntry(entry);
Pick* pick = new Pick;
pick->BuildList(true, proto->ItemLevel);
// Generated Item entry :)
uint32 entry = pick->GenerateId();