mirror of
https://github.com/Shadowss/TravianZ.git
synced 2026-07-26 14:36:06 +00:00
Add T4 Hero Resource and some fix
Add T4 Hero Resource and some fix
This commit is contained in:
@@ -99,6 +99,10 @@ if (!function_exists('admin_config_template_path')) {
|
||||
|
||||
// regenerarea de baza a eroului: acelasi tratament, sa nu fie resetata
|
||||
$cleanupDefaults['%HEROBASEREGEN%'] = array('HERO_BASE_REGEN', 10);
|
||||
$cleanupDefaults['%HEROSILVERPERGOLD%'] = array('HERO_SILVER_PER_GOLD', 10);
|
||||
$cleanupDefaults['%HEROSILVERTOGOLD%'] = array('HERO_SILVER_TO_GOLD', 25);
|
||||
$cleanupDefaults['%HERORESALL%'] = array('HERO_RES_PER_POINT_ALL', 3);
|
||||
$cleanupDefaults['%HERORESONE%'] = array('HERO_RES_PER_POINT_ONE', 10);
|
||||
|
||||
foreach ($overrides as $ovPlaceholder => $ovValue) {
|
||||
if (strpos($text, $ovPlaceholder) !== false) {
|
||||
|
||||
@@ -80,7 +80,31 @@ $heroBaseRegen = isset($_POST['hero_base_regen']) ? (int) $_POST['hero_base_rege
|
||||
if ($heroBaseRegen < 0) { $heroBaseRegen = 0; }
|
||||
if ($heroBaseRegen > 100) { $heroBaseRegen = 100; }
|
||||
|
||||
$text = admin_config_template_contents(array('%HEROBASEREGEN%' => $heroBaseRegen));
|
||||
// Ratele casei de schimb aur <-> argint.
|
||||
$silverPerGold = isset($_POST['hero_silver_per_gold']) ? (int) $_POST['hero_silver_per_gold'] : 10;
|
||||
$silverToGold = isset($_POST['hero_silver_to_gold']) ? (int) $_POST['hero_silver_to_gold'] : 25;
|
||||
|
||||
if ($silverPerGold < 1) { $silverPerGold = 1; }
|
||||
if ($silverPerGold > 10000) { $silverPerGold = 10000; }
|
||||
if ($silverToGold < 1) { $silverToGold = 1; }
|
||||
if ($silverToGold > 10000) { $silverToGold = 10000; }
|
||||
|
||||
// Productia de resurse a eroului (atributul "Resources").
|
||||
$heroResAll = isset($_POST['hero_res_all']) ? (int) $_POST['hero_res_all'] : 3;
|
||||
$heroResOne = isset($_POST['hero_res_one']) ? (int) $_POST['hero_res_one'] : 10;
|
||||
|
||||
if ($heroResAll < 0) { $heroResAll = 0; }
|
||||
if ($heroResAll > 10000) { $heroResAll = 10000; }
|
||||
if ($heroResOne < 0) { $heroResOne = 0; }
|
||||
if ($heroResOne > 10000) { $heroResOne = 10000; }
|
||||
|
||||
$text = admin_config_template_contents(array(
|
||||
'%HEROBASEREGEN%' => $heroBaseRegen,
|
||||
'%HEROSILVERPERGOLD%' => $silverPerGold,
|
||||
'%HEROSILVERTOGOLD%' => $silverToGold,
|
||||
'%HERORESALL%' => $heroResAll,
|
||||
'%HERORESONE%' => $heroResOne,
|
||||
));
|
||||
$text = preg_replace("'%ERRORREPORT%'", $_POST['error'], $text);
|
||||
$text = preg_replace("'%ERROR%'", $_POST['error'], $text);
|
||||
$text = preg_replace("'%SERVERNAME%'", $_POST['servername'], $text);
|
||||
|
||||
@@ -275,6 +275,8 @@ class MYSQLi_DB implements IDbConnection {
|
||||
* @var array Cache of heroes.
|
||||
*/
|
||||
$heroCache = [],
|
||||
// cache per request pentru eroul care produce resurse intr-un sat
|
||||
$heroVillageCache = [],
|
||||
|
||||
/**
|
||||
* @var array Cache of hero field values.
|
||||
|
||||
@@ -23,6 +23,33 @@ use App\Utils\Math;
|
||||
trait DatabaseHeroQueries {
|
||||
|
||||
|
||||
/**
|
||||
* Eroul care produce resurse in satul dat (atributul T4 "Resources").
|
||||
*
|
||||
* Se ia eroul VIU, terminat de antrenat, al carui sat de resedinta (wref)
|
||||
* este satul cerut. Intoarce null daca nu exista.
|
||||
* Rezultatul e cache-uit per request, fiindcă productia se calculeaza des.
|
||||
*/
|
||||
function getHeroForVillage($wid, $use_cache = true) {
|
||||
$wid = (int) $wid;
|
||||
|
||||
if ($use_cache && isset(self::$heroVillageCache[$wid])) {
|
||||
return self::$heroVillageCache[$wid];
|
||||
}
|
||||
|
||||
$q = "SELECT heroid, uid, wref, resources, res_type
|
||||
FROM " . TB_PREFIX . "hero
|
||||
WHERE wref = " . $wid . "
|
||||
AND dead = 0
|
||||
AND COALESCE(intraining, 0) = 0
|
||||
LIMIT 1";
|
||||
|
||||
$result = mysqli_query($this->dblink, $q);
|
||||
$row = $result ? mysqli_fetch_assoc($result) : null;
|
||||
|
||||
return self::$heroVillageCache[$wid] = ($row ?: null);
|
||||
}
|
||||
|
||||
function getHero($uid=0, $all=0, $include_dead = false, $use_cache = true) {
|
||||
list($uid,$all) = $this->escape_input((int) $uid,$all);
|
||||
|
||||
|
||||
+166
-4
@@ -264,6 +264,162 @@ class HeroItems
|
||||
* - anything already in that slot is unequipped first (atomic enough for
|
||||
* a per-user action; both statements touch only this user's rows)
|
||||
*/
|
||||
/* =========================================================================
|
||||
* SCHIMB AUR <-> ARGINT (casa de licitatii)
|
||||
* ===================================================================== */
|
||||
|
||||
const EXCHANGE_OK = 1;
|
||||
const EXCHANGE_NO_HERO = 2;
|
||||
const EXCHANGE_NOT_ENOUGH = 3;
|
||||
const EXCHANGE_INVALID = 4;
|
||||
const EXCHANGE_FAILED = 5;
|
||||
|
||||
/** Cat argint primesti pentru 1 aur (implicit 10, ca in Travian). */
|
||||
public static function silverPerGold()
|
||||
{
|
||||
return defined('HERO_SILVER_PER_GOLD') ? max(1, (int) HERO_SILVER_PER_GOLD) : 10;
|
||||
}
|
||||
|
||||
/** Cat argint costa 1 aur la schimbul invers (implicit 25 - diferenta e marja casei). */
|
||||
public static function silverForOneGold()
|
||||
{
|
||||
return defined('HERO_SILVER_TO_GOLD') ? max(1, (int) HERO_SILVER_TO_GOLD) : 25;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aur -> argint. $gold = cat aur dai.
|
||||
*
|
||||
* Ambele scrieri (scaderea aurului si adaugarea argintului) sunt intr-o
|
||||
* TRANZACTIE: sunt tabele diferite (users si hero), iar fara tranzactie o
|
||||
* eroare intre ele ar lasa jucatorul fara aur si fara argint. Scaderea are
|
||||
* conditia "gold >= ?" chiar in UPDATE, deci doua cereri trimise simultan nu
|
||||
* pot cheltui acelasi aur de doua ori.
|
||||
*/
|
||||
public function exchangeGoldToSilver($uid, $gold)
|
||||
{
|
||||
$uid = (int) $uid;
|
||||
$gold = (int) $gold;
|
||||
|
||||
if ($gold <= 0 || $gold > 100000) {
|
||||
return self::EXCHANGE_INVALID;
|
||||
}
|
||||
|
||||
$silver = $gold * self::silverPerGold();
|
||||
|
||||
return $this->runExchange($uid, $gold, $silver, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Argint -> aur. $gold = cat aur vrei sa primesti.
|
||||
*/
|
||||
public function exchangeSilverToGold($uid, $gold)
|
||||
{
|
||||
$uid = (int) $uid;
|
||||
$gold = (int) $gold;
|
||||
|
||||
if ($gold <= 0 || $gold > 100000) {
|
||||
return self::EXCHANGE_INVALID;
|
||||
}
|
||||
|
||||
$silver = $gold * self::silverForOneGold();
|
||||
|
||||
return $this->runExchange($uid, $gold, $silver, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executa schimbul. $goldToSilver = true inseamna "dai aur, primesti argint".
|
||||
*/
|
||||
private function runExchange($uid, $gold, $silver, $goldToSilver)
|
||||
{
|
||||
// Fara erou nu exista unde tine argintul.
|
||||
if ($this->heroRowId($uid) === 0) {
|
||||
return self::EXCHANGE_NO_HERO;
|
||||
}
|
||||
|
||||
$this->db->begin_transaction();
|
||||
|
||||
try {
|
||||
if ($goldToSilver) {
|
||||
$take = $this->db->prepare(
|
||||
"UPDATE " . TB_PREFIX . "users SET gold = gold - ? WHERE id = ? AND gold >= ? LIMIT 1"
|
||||
);
|
||||
$take->bind_param('iii', $gold, $uid, $gold);
|
||||
$take->execute();
|
||||
$taken = $take->affected_rows;
|
||||
$take->close();
|
||||
|
||||
if ($taken < 1) {
|
||||
$this->db->rollback();
|
||||
return self::EXCHANGE_NOT_ENOUGH;
|
||||
}
|
||||
|
||||
$give = $this->db->prepare(
|
||||
"UPDATE " . TB_PREFIX . "hero SET silver = silver + ? WHERE uid = ? LIMIT 1"
|
||||
);
|
||||
$give->bind_param('ii', $silver, $uid);
|
||||
$give->execute();
|
||||
$given = $give->affected_rows;
|
||||
$give->close();
|
||||
|
||||
if ($given < 1) {
|
||||
$this->db->rollback();
|
||||
return self::EXCHANGE_FAILED;
|
||||
}
|
||||
|
||||
} else {
|
||||
$take = $this->db->prepare(
|
||||
"UPDATE " . TB_PREFIX . "hero SET silver = silver - ? WHERE uid = ? AND silver >= ? LIMIT 1"
|
||||
);
|
||||
$take->bind_param('iii', $silver, $uid, $silver);
|
||||
$take->execute();
|
||||
$taken = $take->affected_rows;
|
||||
$take->close();
|
||||
|
||||
if ($taken < 1) {
|
||||
$this->db->rollback();
|
||||
return self::EXCHANGE_NOT_ENOUGH;
|
||||
}
|
||||
|
||||
$give = $this->db->prepare(
|
||||
"UPDATE " . TB_PREFIX . "users SET gold = gold + ? WHERE id = ? LIMIT 1"
|
||||
);
|
||||
$give->bind_param('ii', $gold, $uid);
|
||||
$give->execute();
|
||||
$given = $give->affected_rows;
|
||||
$give->close();
|
||||
|
||||
if ($given < 1) {
|
||||
$this->db->rollback();
|
||||
return self::EXCHANGE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->commit();
|
||||
|
||||
return self::EXCHANGE_OK;
|
||||
|
||||
} catch (Throwable $e) {
|
||||
$this->db->rollback();
|
||||
return self::EXCHANGE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/** Id-ul randului de erou al jucatorului, 0 daca nu exista. */
|
||||
private function heroRowId($uid)
|
||||
{
|
||||
$uid = (int) $uid;
|
||||
$stmt = $this->db->prepare(
|
||||
"SELECT heroid FROM " . TB_PREFIX . "hero WHERE uid = ? LIMIT 1"
|
||||
);
|
||||
$stmt->bind_param('i', $uid);
|
||||
$stmt->execute();
|
||||
$stmt->bind_result($heroid);
|
||||
$found = $stmt->fetch();
|
||||
$stmt->close();
|
||||
|
||||
return $found ? (int) $heroid : 0;
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* DISPONIBILITATEA EROULUI PENTRU SCHIMBAREA ECHIPAMENTULUI
|
||||
* ===================================================================== */
|
||||
@@ -547,14 +703,20 @@ class HeroItems
|
||||
if (!$hero) {
|
||||
return self::USE_INVALID;
|
||||
}
|
||||
// Refund all spent points: 5 free points per level gained (same
|
||||
// convention as Automation::calculateLevelUp). Attributes return to 0.
|
||||
// FIX: un erou porneste cu 5 puncte la nivelul 0 (vezi INSERT-ul din
|
||||
// 37_train.tpl), iar fiecare nivel mai da 5 (Automation::calculateLevelUp).
|
||||
// Formula veche, "level * 5", uita punctele initiale: cartea returna cu 5
|
||||
// mai putin decat avusese jucatorul, iar la nivelul 0 le pierdea pe toate
|
||||
// si lasa eroul cu 0 puncte si toate atributele pe zero.
|
||||
$level = (int) $hero['level'];
|
||||
$points = $level * 5;
|
||||
$points = 5 + ($level * 5);
|
||||
|
||||
// resources intra si el in reset (punctele se redistribuie doar cu cartea);
|
||||
// res_type ramane neatins - alegerea resursei se schimba oricand, gratis.
|
||||
$stmt = $this->db->prepare(
|
||||
"UPDATE " . TB_PREFIX . "hero
|
||||
SET points = ?, attack = 0, defence = 0, attackbonus = 0,
|
||||
defencebonus = 0, regeneration = 0
|
||||
defencebonus = 0, regeneration = 0, resources = 0
|
||||
WHERE heroid = ? LIMIT 1"
|
||||
);
|
||||
$heroid = (int) $hero['heroid'];
|
||||
|
||||
@@ -2818,6 +2818,17 @@ tz_def('HERO_T4_TAB_ITEMS', 'Inventory');
|
||||
tz_def('HERO_T4_TAB_ADVENTURES', 'Adventures');
|
||||
tz_def('HERO_T4_TAB_AUCTION', 'Auctions');
|
||||
|
||||
tz_def('HERO_EXCHANGE', 'Exchange office');
|
||||
tz_def('HERO_EXCHANGE_G2S', 'Gold to silver');
|
||||
tz_def('HERO_EXCHANGE_S2G', 'Silver to gold');
|
||||
tz_def('HERO_EXCHANGE_OK', 'Exchange completed.');
|
||||
tz_def('HERO_EXCHANGE_NOTENOUGH', 'You do not have enough for this exchange.');
|
||||
tz_def('HERO_EXCHANGE_FAIL', 'The exchange could not be completed.');
|
||||
tz_def('HERO_EXCHANGE_HINT', 'The amount you type is the gold given or received; silver is calculated at the rate shown.');
|
||||
tz_def('HERO_RES_PRODUCTION', 'Resources');
|
||||
tz_def('HERO_RES_TYPE', 'Produced resource');
|
||||
tz_def('HERO_RES_ALL', 'All resources');
|
||||
tz_def('HERO_RES_TYPE_HINT', 'Can be changed at any time, free of charge.');
|
||||
tz_def('HERO_SILVER', 'Silver');
|
||||
tz_def('HERO_EXPERIENCE', 'Experience');
|
||||
tz_def('RESOURCES', 'Resources');
|
||||
|
||||
@@ -2803,6 +2803,17 @@ tz_def('HERO_ITEM_USE_FAIL', 'Acest obiect nu poate fi folosit acum.');
|
||||
tz_def('HERO_QUANTITY', 'Cantitate');
|
||||
tz_def('HERO_RELEASE_ANIMALS', 'Elibereaza');
|
||||
tz_def('HERO_RELEASE_CONFIRM', 'Eliberezi aceste animale? Vor disparea definitiv.');
|
||||
tz_def('HERO_EXCHANGE', 'Casa de schimb');
|
||||
tz_def('HERO_EXCHANGE_G2S', 'Aur in argint');
|
||||
tz_def('HERO_EXCHANGE_S2G', 'Argint in aur');
|
||||
tz_def('HERO_EXCHANGE_OK', 'Schimb efectuat.');
|
||||
tz_def('HERO_EXCHANGE_NOTENOUGH', 'Nu ai suficient pentru acest schimb.');
|
||||
tz_def('HERO_EXCHANGE_FAIL', 'Schimbul nu a putut fi efectuat.');
|
||||
tz_def('HERO_EXCHANGE_HINT', 'Valoarea introdusa e aurul dat sau primit; argintul se calculeaza la rata afisata.');
|
||||
tz_def('HERO_RES_PRODUCTION', 'Resurse');
|
||||
tz_def('HERO_RES_TYPE', 'Resursa produsa');
|
||||
tz_def('HERO_RES_ALL', 'Toate resursele');
|
||||
tz_def('HERO_RES_TYPE_HINT', 'Se poate schimba oricand, gratuit.');
|
||||
tz_def('HERO_SILVER', 'Argint');
|
||||
tz_def('HERO_SLOT_1', 'Coif');
|
||||
tz_def('HERO_SLOT_2', 'Armura');
|
||||
|
||||
@@ -43,6 +43,9 @@ class Village {
|
||||
public $enforcetome = [];
|
||||
public $enforcetoyou = [];
|
||||
public $enforceoasis = [];
|
||||
|
||||
/** cache per sat pentru productia adusa de erou (null = neincarcat) */
|
||||
private $heroProd = null;
|
||||
public $currentcel = 0;
|
||||
public $currentfestival = 0;
|
||||
public $allcrop = 0;
|
||||
@@ -306,11 +309,74 @@ class Village {
|
||||
$amount += $amount / 100 * $bonusPct;
|
||||
}
|
||||
|
||||
// Productia de resurse a eroului (atributul "Resources", ca in T4).
|
||||
// Se adauga DUPA bonusurile de cladiri si oaze (alea se aplica doar campurilor)
|
||||
// dar INAINTE de bonusul de 25% si de inmultirea cu SPEED, fiindca in T4 si
|
||||
// bonusul de 25% si viteza serverului se aplica si productiei eroului.
|
||||
$amount += $this->getHeroProdFor($type);
|
||||
|
||||
if ($this->sess->{$cfg['sessionBonus']} == 1) $amount *= 1.25;
|
||||
|
||||
return round($amount * SPEED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Productia orara adusa de atributul "Resources" al eroului, pentru satul asta.
|
||||
*
|
||||
* Regula T4: fiecare punct produce 3 din FIECARE resursa (res_type = 0) sau 10
|
||||
* dintr-un singur tip (res_type = 1..4 pentru lemn/lut/fier/cereale).
|
||||
* Bonusul merge in satul in care se afla eroul (hero.wref), deci mutarea
|
||||
* eroului muta si productia.
|
||||
*
|
||||
* Randul de erou se citeste O SINGURA DATA per instanta de sat.
|
||||
*/
|
||||
private function getHeroProdFor(string $type): float {
|
||||
|
||||
if ($this->heroProd === null) {
|
||||
$this->heroProd = $this->loadHeroProd();
|
||||
}
|
||||
|
||||
return $this->heroProd[$type] ?? 0.0;
|
||||
}
|
||||
|
||||
/** Citeste eroul acestui sat si transforma punctele in productie per resursa. */
|
||||
private function loadHeroProd(): array {
|
||||
|
||||
$empty = ['wood' => 0.0, 'clay' => 0.0, 'iron' => 0.0, 'crop' => 0.0];
|
||||
|
||||
if (!defined('NEW_FUNCTIONS_HERO_T4') || !NEW_FUNCTIONS_HERO_T4) {
|
||||
return $empty;
|
||||
}
|
||||
|
||||
$row = $this->db->getHeroForVillage($this->wid);
|
||||
|
||||
if (!$row) {
|
||||
return $empty;
|
||||
}
|
||||
|
||||
$points = (int) $row['resources'];
|
||||
|
||||
if ($points <= 0) {
|
||||
return $empty;
|
||||
}
|
||||
|
||||
$resType = (int) $row['res_type'];
|
||||
$map = [1 => 'wood', 2 => 'clay', 3 => 'iron', 4 => 'crop'];
|
||||
|
||||
// 0 = raspandit egal: 3 din fiecare. Altfel: 10 dintr-un singur tip.
|
||||
if ($resType === 0 || !isset($map[$resType])) {
|
||||
$each = $points * (defined('HERO_RES_PER_POINT_ALL') ? (int) HERO_RES_PER_POINT_ALL : 3);
|
||||
return ['wood' => $each, 'clay' => $each, 'iron' => $each, 'crop' => $each];
|
||||
}
|
||||
|
||||
$single = $points * (defined('HERO_RES_PER_POINT_ONE') ? (int) HERO_RES_PER_POINT_ONE : 10);
|
||||
|
||||
$out = $empty;
|
||||
$out[$map[$resType]] = $single;
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* W1 #4: scans the f1..f38 fields ONLY once per load (instead of 4 passes)
|
||||
* and buckets them by type.
|
||||
|
||||
Reference in New Issue
Block a user