mirror of
https://github.com/Shadowss/TravianZ.git
synced 2026-08-09 21:01:00 +00:00
6d02a8ff03
Fix Alliance Level Require Bonus
685 lines
23 KiB
PHP
685 lines
23 KiB
PHP
<?php
|
|
|
|
#################################################################################
|
|
## -= YOU MAY NOT REMOVE OR CHANGE THIS NOTICE =- ##
|
|
## --------------------------------------------------------------------------- ##
|
|
## Filename : AllianceBonus.php ##
|
|
## Type : AllianceBonus port ##
|
|
## --------------------------------------------------------------------------- ##
|
|
## Developed by : Shadow ##
|
|
## Project : TravianZ ##
|
|
## GitHub : https://github.com/Shadowss/TravianZ ##
|
|
## --------------------------------------------------------------------------- ##
|
|
## License : TravianZ Project ##
|
|
## Copyright : TravianZ (c) 2010-2026. All rights reserved. ##
|
|
## --------------------------------------------------------------------------- ##
|
|
#################################################################################
|
|
## ##
|
|
## Alliance members donate resources, allowing the alliance to unlock four ##
|
|
## bonuses, each with five levels: ##
|
|
## ##
|
|
## 1 Recruitment - Faster troop training in all military buildings ##
|
|
## 2 Philosophy - Increased Culture Point production ##
|
|
## 3 Metallurgy - Higher attack and defense values (in addition to Smithy ##
|
|
## upgrades) ##
|
|
## 4 Commerce - Increased merchant carrying capacity ##
|
|
## ##
|
|
## The mechanics follow Travian T4: the type of resource donated does not ##
|
|
## matter, only the total amount; while a bonus level is being unlocked, ##
|
|
## donations to that bonus are temporarily disabled; each player has a daily ##
|
|
## donation limit that increases with the alliance level; and new members ##
|
|
## gradually gain access to higher bonus levels. ##
|
|
#################################################################################
|
|
|
|
class AllianceBonus
|
|
{
|
|
const RECRUITMENT = 1;
|
|
const PHILOSOPHY = 2;
|
|
const METALLURGY = 3;
|
|
const COMMERCE = 4;
|
|
|
|
const MAX_LEVEL = 5;
|
|
|
|
// rezultate pentru donate()
|
|
const DONATE_OK = 0;
|
|
const DONATE_DISABLED = 1;
|
|
const DONATE_NO_ALLIANCE = 2;
|
|
const DONATE_UPGRADING = 3;
|
|
const DONATE_LIMIT = 4;
|
|
const DONATE_RESOURCES = 5;
|
|
const DONATE_INVALID = 6;
|
|
const DONATE_NO_GOLD = 7;
|
|
|
|
private $db;
|
|
|
|
/** cache per cerere: nivelurile fiecarei aliante deja citite */
|
|
private static $levelCache = array();
|
|
|
|
public function __construct()
|
|
{
|
|
global $database;
|
|
$this->db = $database->dblink;
|
|
}
|
|
|
|
/**
|
|
* Functiile sunt pornite? Verificam si flagul, si existenta tabelei, ca sa
|
|
* nu cada jocul pe un server care nu a rulat inca migrarea SQL.
|
|
*/
|
|
public static function enabled()
|
|
{
|
|
static $ok = null;
|
|
|
|
if ($ok !== null) {
|
|
return $ok;
|
|
}
|
|
|
|
if (!defined('NEW_FUNCTIONS_ALLIANCE_BONUSES') || !NEW_FUNCTIONS_ALLIANCE_BONUSES) {
|
|
return $ok = false;
|
|
}
|
|
|
|
global $database;
|
|
$res = @mysqli_query($database->dblink,
|
|
"SHOW TABLES LIKE '" . TB_PREFIX . "alliance_bonus'");
|
|
|
|
return $ok = ($res && mysqli_num_rows($res) > 0);
|
|
}
|
|
|
|
/** Lista tipurilor, cu cheia de limba si iconita. */
|
|
public static function types()
|
|
{
|
|
return array(
|
|
self::RECRUITMENT => array('key' => 'recruitment', 'lang' => 'ALLYBONUS_RECRUITMENT'),
|
|
self::PHILOSOPHY => array('key' => 'philosophy', 'lang' => 'ALLYBONUS_PHILOSOPHY'),
|
|
self::METALLURGY => array('key' => 'metallurgy', 'lang' => 'ALLYBONUS_METALLURGY'),
|
|
self::COMMERCE => array('key' => 'commerce', 'lang' => 'ALLYBONUS_COMMERCE'),
|
|
);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Tabele de valori (din config, cu rezerva pe valorile din T4) */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
private static function listFromConst($name, $fallback)
|
|
{
|
|
$raw = defined($name) ? (string) constant($name) : $fallback;
|
|
$out = array();
|
|
|
|
foreach (explode(',', $raw) as $v) {
|
|
$v = trim($v);
|
|
|
|
if ($v !== '' && is_numeric($v)) {
|
|
$out[] = (float) $v;
|
|
}
|
|
}
|
|
|
|
return $out ? $out : array_map('floatval', explode(',', $fallback));
|
|
}
|
|
|
|
/** Resurse necesare pentru a trece de la $level la $level+1. */
|
|
public static function costFor($level)
|
|
{
|
|
$costs = self::listFromConst('ALLIANCE_BONUS_COSTS',
|
|
'1200000,5600000,17100000,51200000,153600000');
|
|
|
|
return isset($costs[$level]) ? (float) $costs[$level] : 0.0;
|
|
}
|
|
|
|
/** Durata upgrade-ului, in secunde, scalata cu viteza serverului. */
|
|
public static function upgradeSeconds($level)
|
|
{
|
|
$hours = self::listFromConst('ALLIANCE_BONUS_HOURS', '24,48,72,96,120');
|
|
$h = isset($hours[$level]) ? (float) $hours[$level] : 24.0;
|
|
$speed = (defined('SPEED') && SPEED > 0) ? (float) SPEED : 1.0;
|
|
|
|
return (int) max(60, round($h * 3600 / $speed));
|
|
}
|
|
|
|
/**
|
|
* Plafonul zilnic de donatie al unui jucator, dupa cel mai mare nivel
|
|
* deblocat in alianta. Se scaleaza cu viteza serverului, ca in T4.
|
|
*/
|
|
public static function dailyLimit($highestLevel)
|
|
{
|
|
$limits = self::listFromConst('ALLIANCE_BONUS_DAILY',
|
|
'300000,300000,400000,550000,750000,1000000');
|
|
|
|
$idx = max(0, min(count($limits) - 1, (int) $highestLevel));
|
|
$val = (float) $limits[$idx];
|
|
$speed = (defined('SPEED') && SPEED > 0) ? (float) SPEED : 1.0;
|
|
|
|
return (float) round($val * $speed);
|
|
}
|
|
|
|
/** Procentul acordat de un nivel, pentru un tip de bonus. */
|
|
public static function percentFor($btype, $level)
|
|
{
|
|
$level = max(0, min(self::MAX_LEVEL, (int) $level));
|
|
|
|
if ($level === 0) {
|
|
return 0.0;
|
|
}
|
|
|
|
$small = defined('ALLIANCE_BONUS_PCT_SMALL') ? (float) ALLIANCE_BONUS_PCT_SMALL : 2.0;
|
|
$large = defined('ALLIANCE_BONUS_PCT_LARGE') ? (float) ALLIANCE_BONUS_PCT_LARGE : 4.0;
|
|
|
|
// Recruitment si Philosophy cresc cu 2% pe nivel, Metallurgy si
|
|
// Commerce cu 4% pe nivel (vezi tabelul din T4).
|
|
$step = in_array((int) $btype, array(self::METALLURGY, self::COMMERCE), true)
|
|
? $large : $small;
|
|
|
|
return $level * $step;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Citire */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
/**
|
|
* Starea completa a bonusurilor unei aliante: nivel, progres, upgrade activ.
|
|
* Randurile lipsa se completeaza cu nivel 0, deci apelantul primeste mereu
|
|
* toate cele patru tipuri.
|
|
*/
|
|
public function getState($aid)
|
|
{
|
|
$aid = (int) $aid;
|
|
$out = array();
|
|
|
|
foreach (array_keys(self::types()) as $btype) {
|
|
$out[$btype] = array(
|
|
'btype' => $btype,
|
|
'level' => 0,
|
|
'pool' => 0.0,
|
|
'upgrade_end' => 0,
|
|
);
|
|
}
|
|
|
|
if ($aid <= 0 || !self::enabled()) {
|
|
return $out;
|
|
}
|
|
|
|
$res = mysqli_query($this->db,
|
|
"SELECT btype, level, pool, upgrade_end FROM " . TB_PREFIX . "alliance_bonus
|
|
WHERE aid = " . $aid);
|
|
|
|
while ($res && ($row = mysqli_fetch_assoc($res))) {
|
|
$b = (int) $row['btype'];
|
|
|
|
if (isset($out[$b])) {
|
|
$out[$b] = array(
|
|
'btype' => $b,
|
|
'level' => (int) $row['level'],
|
|
'pool' => (float) $row['pool'],
|
|
'upgrade_end' => (int) $row['upgrade_end'],
|
|
);
|
|
}
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Nivelurile efective ale unei aliante, ca array btype => nivel.
|
|
* Cache-uit pe cerere: se citeste des (lupte, instruire, productie).
|
|
*/
|
|
public function getLevels($aid)
|
|
{
|
|
$aid = (int) $aid;
|
|
|
|
if (isset(self::$levelCache[$aid])) {
|
|
return self::$levelCache[$aid];
|
|
}
|
|
|
|
$levels = array();
|
|
|
|
foreach (array_keys(self::types()) as $btype) {
|
|
$levels[$btype] = 0;
|
|
}
|
|
|
|
if ($aid > 0 && self::enabled()) {
|
|
$res = mysqli_query($this->db,
|
|
"SELECT btype, level FROM " . TB_PREFIX . "alliance_bonus WHERE aid = " . $aid);
|
|
|
|
while ($res && ($row = mysqli_fetch_assoc($res))) {
|
|
$b = (int) $row['btype'];
|
|
|
|
if (isset($levels[$b])) {
|
|
$levels[$b] = (int) $row['level'];
|
|
}
|
|
}
|
|
}
|
|
|
|
return self::$levelCache[$aid] = $levels;
|
|
}
|
|
|
|
/** Cel mai mare nivel deblocat in alianta (pentru plafonul de donatie). */
|
|
public function highestLevel($aid)
|
|
{
|
|
$levels = $this->getLevels($aid);
|
|
|
|
return $levels ? max($levels) : 0;
|
|
}
|
|
|
|
/**
|
|
* Nivelul de care beneficiaza EFECTIV un jucator.
|
|
*
|
|
* Membrii noi capata acces treptat: nivelul 1 imediat, nivelul 2 dupa 24h,
|
|
* nivelul 3 dupa 48h si asa mai departe (scalat cu viteza serverului).
|
|
* Asa nu se poate sari dintr-o alianta in alta doar ca sa culegi bonusuri.
|
|
*/
|
|
public function effectiveLevel($uid, $btype)
|
|
{
|
|
if (!self::enabled()) {
|
|
return 0;
|
|
}
|
|
|
|
$uid = (int) $uid;
|
|
$res = mysqli_query($this->db,
|
|
"SELECT alliance, alliance_joined FROM " . TB_PREFIX . "users WHERE id = " . $uid . " LIMIT 1");
|
|
$row = $res ? mysqli_fetch_assoc($res) : null;
|
|
|
|
if (!$row || (int) $row['alliance'] <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
$levels = $this->getLevels((int) $row['alliance']);
|
|
$level = isset($levels[(int) $btype]) ? (int) $levels[(int) $btype] : 0;
|
|
|
|
if ($level <= 1) {
|
|
return $level; // nivelul 1 e disponibil imediat
|
|
}
|
|
|
|
$joined = (int) $row['alliance_joined'];
|
|
|
|
// 0 sau 1 inseamna membru dinainte de aceasta functie: primeste tot
|
|
if ($joined <= 1) {
|
|
return $level;
|
|
}
|
|
|
|
$speed = (defined('SPEED') && SPEED > 0) ? (float) SPEED : 1.0;
|
|
$elapsed = time() - $joined;
|
|
|
|
// nivelul N devine disponibil dupa (N-1) * 24h de la intrare
|
|
$allowed = 1 + (int) floor($elapsed / max(60, (86400 / $speed)));
|
|
|
|
return max(0, min($level, $allowed));
|
|
}
|
|
|
|
/**
|
|
* Cat mai are de asteptat un jucator pana i se deschide nivelul urmator.
|
|
*
|
|
* Intoarce numarul de secunde, sau 0 daca deja beneficiaza de tot ce a
|
|
* deblocat alianta. Se foloseste in pagina de bonusuri: fara asta, un
|
|
* membru nou vede "nivel 2" dar simte efectul nivelului 1 si nu are cum
|
|
* sa-si dea seama de ce.
|
|
*/
|
|
public function waitingFor($uid, $btype)
|
|
{
|
|
if (!self::enabled()) {
|
|
return 0;
|
|
}
|
|
|
|
$uid = (int) $uid;
|
|
$res = mysqli_query($this->db,
|
|
"SELECT alliance, alliance_joined FROM " . TB_PREFIX . "users WHERE id = " . $uid . " LIMIT 1");
|
|
$row = $res ? mysqli_fetch_assoc($res) : null;
|
|
|
|
if (!$row || (int) $row['alliance'] <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
$levels = $this->getLevels((int) $row['alliance']);
|
|
$unlocked = isset($levels[(int) $btype]) ? (int) $levels[(int) $btype] : 0;
|
|
$effective = $this->effectiveLevel($uid, $btype);
|
|
|
|
if ($effective >= $unlocked) {
|
|
return 0; // beneficiaza deja de tot
|
|
}
|
|
|
|
$joined = (int) $row['alliance_joined'];
|
|
|
|
if ($joined <= 1) {
|
|
return 0;
|
|
}
|
|
|
|
$speed = (defined('SPEED') && SPEED > 0) ? (float) SPEED : 1.0;
|
|
$step = max(60, (int) (86400 / $speed));
|
|
|
|
// nivelul (effective + 1) devine disponibil dupa effective * step
|
|
$ready = $joined + ($effective * $step);
|
|
|
|
return max(0, $ready - time());
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Donatii */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
/** Cat a donat un jucator azi. */
|
|
public function donatedToday($uid)
|
|
{
|
|
if (!self::enabled()) {
|
|
return 0.0;
|
|
}
|
|
|
|
$uid = (int) $uid;
|
|
$day = (int) floor(time() / 86400);
|
|
|
|
$res = mysqli_query($this->db,
|
|
"SELECT amount FROM " . TB_PREFIX . "alliance_donation
|
|
WHERE uid = " . $uid . " AND day = " . $day . " LIMIT 1");
|
|
$row = $res ? mysqli_fetch_assoc($res) : null;
|
|
|
|
return $row ? (float) $row['amount'] : 0.0;
|
|
}
|
|
|
|
/**
|
|
* Doneaza resurse catre un bonus.
|
|
*
|
|
* $amounts - array cu patru valori: lemn, lut, fier, cereale
|
|
* $triple - daca jucatorul plateste aur ca donatia sa conteze intreit
|
|
*
|
|
* Tipul resursei nu conteaza, doar totalul; resursele se scad din satul
|
|
* activ. Intoarce una dintre constantele DONATE_*.
|
|
*/
|
|
public function donate($uid, $wref, $btype, array $amounts, $triple = false)
|
|
{
|
|
global $database, $session;
|
|
|
|
if (!self::enabled()) {
|
|
return self::DONATE_DISABLED;
|
|
}
|
|
|
|
$uid = (int) $uid;
|
|
$wref = (int) $wref;
|
|
$btype = (int) $btype;
|
|
|
|
if (!isset(self::types()[$btype])) {
|
|
return self::DONATE_INVALID;
|
|
}
|
|
|
|
// sumele trebuie sa fie intregi pozitivi
|
|
$clean = array();
|
|
$total = 0.0;
|
|
|
|
foreach (array_slice($amounts, 0, 4) as $a) {
|
|
$a = (float) $a;
|
|
|
|
if ($a < 0 || !is_finite($a)) {
|
|
return self::DONATE_INVALID;
|
|
}
|
|
|
|
$a = floor($a);
|
|
$clean[] = $a;
|
|
$total += $a;
|
|
}
|
|
|
|
while (count($clean) < 4) {
|
|
$clean[] = 0.0;
|
|
}
|
|
|
|
if ($total <= 0) {
|
|
return self::DONATE_INVALID;
|
|
}
|
|
|
|
// alianta jucatorului
|
|
$res = mysqli_query($this->db,
|
|
"SELECT alliance FROM " . TB_PREFIX . "users WHERE id = " . $uid . " LIMIT 1");
|
|
$row = $res ? mysqli_fetch_assoc($res) : null;
|
|
$aid = $row ? (int) $row['alliance'] : 0;
|
|
|
|
if ($aid <= 0) {
|
|
return self::DONATE_NO_ALLIANCE;
|
|
}
|
|
|
|
// bonusul nu trebuie sa fie in curs de upgrade
|
|
$state = $this->getState($aid);
|
|
|
|
if ($state[$btype]['upgrade_end'] > time()) {
|
|
return self::DONATE_UPGRADING;
|
|
}
|
|
|
|
if ($state[$btype]['level'] >= self::MAX_LEVEL) {
|
|
return self::DONATE_INVALID;
|
|
}
|
|
|
|
// valoarea contorizata (triplata sau nu) si plafonul zilnic
|
|
$counted = $triple ? $total * 3 : $total;
|
|
$limit = self::dailyLimit($this->highestLevel($aid));
|
|
$already = $this->donatedToday($uid);
|
|
|
|
if ($already + $counted > $limit) {
|
|
return self::DONATE_LIMIT;
|
|
}
|
|
|
|
// aurul pentru triplare
|
|
if ($triple) {
|
|
$cost = defined('ALLIANCE_BONUS_TRIPLE_GOLD') ? (int) ALLIANCE_BONUS_TRIPLE_GOLD : 3;
|
|
|
|
if ((int) $session->gold < $cost) {
|
|
return self::DONATE_NO_GOLD;
|
|
}
|
|
}
|
|
|
|
// Resursele trebuie sa existe in sat.
|
|
// FIX: getResource() nu exista in clasa de baza de date; randul satului
|
|
// (cu wood/clay/iron/crop) se citeste cu getVillage(), fara cache, ca sa
|
|
// vedem valorile de dupa ultima productie, nu unele vechi de cateva zeci
|
|
// de secunde.
|
|
$vres = $database->getVillage($wref, 0, false);
|
|
|
|
if (!$vres) {
|
|
return self::DONATE_RESOURCES;
|
|
}
|
|
|
|
$fields = array('wood', 'clay', 'iron', 'crop');
|
|
|
|
foreach ($fields as $i => $f) {
|
|
if ((float) $vres[$f] < $clean[$i]) {
|
|
return self::DONATE_RESOURCES;
|
|
}
|
|
}
|
|
|
|
/* ---- de aici incolo modificam starea; totul intr-o tranzactie ---- */
|
|
mysqli_query($this->db, "START TRANSACTION");
|
|
|
|
// ATENTIE LA SEMN: modifyResource cu modul 0 SCADE deja
|
|
// ("wood = wood - $wood"). Trimiterea de valori negative ar fi
|
|
// ADAUGAT resurse - aceeasi capcana ca la aurul de la demolare.
|
|
$ok = $database->modifyResource($wref, $clean[0], $clean[1], $clean[2], $clean[3], 0);
|
|
|
|
if (!$ok) {
|
|
mysqli_query($this->db, "ROLLBACK");
|
|
return self::DONATE_RESOURCES;
|
|
}
|
|
|
|
// randul de bonus poate lipsi: il cream la prima donatie
|
|
mysqli_query($this->db,
|
|
"INSERT INTO " . TB_PREFIX . "alliance_bonus (aid, btype, level, pool, upgrade_end)
|
|
VALUES (" . $aid . ", " . $btype . ", 0, 0, 0)
|
|
ON DUPLICATE KEY UPDATE aid = aid");
|
|
|
|
// adaugam in fond DOAR daca bonusul tot nu e in upgrade (protejeaza
|
|
// impotriva a doua donatii simultane care ar sari peste verificare)
|
|
$res = mysqli_query($this->db,
|
|
"UPDATE " . TB_PREFIX . "alliance_bonus
|
|
SET pool = pool + " . $counted . "
|
|
WHERE aid = " . $aid . " AND btype = " . $btype . "
|
|
AND upgrade_end <= " . time() . " AND level < " . self::MAX_LEVEL . " LIMIT 1");
|
|
|
|
if (!$res || mysqli_affected_rows($this->db) === 0) {
|
|
mysqli_query($this->db, "ROLLBACK");
|
|
return self::DONATE_UPGRADING;
|
|
}
|
|
|
|
$day = (int) floor(time() / 86400);
|
|
mysqli_query($this->db,
|
|
"INSERT INTO " . TB_PREFIX . "alliance_donation (uid, day, amount)
|
|
VALUES (" . $uid . ", " . $day . ", " . $counted . ")
|
|
ON DUPLICATE KEY UPDATE amount = amount + " . $counted);
|
|
|
|
mysqli_query($this->db,
|
|
"INSERT INTO " . TB_PREFIX . "alliance_donation_log (aid, uid, btype, amount, time)
|
|
VALUES (" . $aid . ", " . $uid . ", " . $btype . ", " . $counted . ", " . time() . ")");
|
|
|
|
if ($triple) {
|
|
$cost = defined('ALLIANCE_BONUS_TRIPLE_GOLD') ? (int) ALLIANCE_BONUS_TRIPLE_GOLD : 3;
|
|
$database->modifyGold($uid, $cost, 0);
|
|
$session->gold -= $cost;
|
|
}
|
|
|
|
mysqli_query($this->db, "COMMIT");
|
|
|
|
// daca fondul a atins pragul, pornim upgrade-ul
|
|
$this->startUpgradeIfReady($aid, $btype);
|
|
|
|
unset(self::$levelCache[$aid]);
|
|
|
|
return self::DONATE_OK;
|
|
}
|
|
|
|
/**
|
|
* Porneste numaratoarea daca fondul acopera costul nivelului urmator.
|
|
* Costul se scade din fond, ca surplusul sa se reporteze la nivelul urmator.
|
|
*/
|
|
public function startUpgradeIfReady($aid, $btype)
|
|
{
|
|
$aid = (int) $aid;
|
|
$btype = (int) $btype;
|
|
|
|
$res = mysqli_query($this->db,
|
|
"SELECT level, pool, upgrade_end FROM " . TB_PREFIX . "alliance_bonus
|
|
WHERE aid = " . $aid . " AND btype = " . $btype . " LIMIT 1");
|
|
$row = $res ? mysqli_fetch_assoc($res) : null;
|
|
|
|
if (!$row || (int) $row['upgrade_end'] > time() || (int) $row['level'] >= self::MAX_LEVEL) {
|
|
return false;
|
|
}
|
|
|
|
$level = (int) $row['level'];
|
|
$cost = self::costFor($level);
|
|
|
|
if ($cost <= 0 || (float) $row['pool'] < $cost) {
|
|
return false;
|
|
}
|
|
|
|
$end = time() + self::upgradeSeconds($level);
|
|
|
|
mysqli_query($this->db,
|
|
"UPDATE " . TB_PREFIX . "alliance_bonus
|
|
SET pool = pool - " . $cost . ", upgrade_end = " . $end . "
|
|
WHERE aid = " . $aid . " AND btype = " . $btype . "
|
|
AND upgrade_end <= " . time() . " LIMIT 1");
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Finalizeaza upgrade-urile expirate. Se apeleaza din Automation.
|
|
* Dupa crestere, verificam din nou fondul: daca surplusul acopera si
|
|
* nivelul urmator, upgrade-ul continua fara alta donatie.
|
|
*/
|
|
public function processUpgrades()
|
|
{
|
|
if (!self::enabled()) {
|
|
return 0;
|
|
}
|
|
|
|
$now = time();
|
|
$done = 0;
|
|
|
|
$res = mysqli_query($this->db,
|
|
"SELECT aid, btype FROM " . TB_PREFIX . "alliance_bonus
|
|
WHERE upgrade_end > 0 AND upgrade_end <= " . $now);
|
|
|
|
$rows = array();
|
|
|
|
while ($res && ($row = mysqli_fetch_assoc($res))) {
|
|
$rows[] = array((int) $row['aid'], (int) $row['btype']);
|
|
}
|
|
|
|
foreach ($rows as $r) {
|
|
list($aid, $btype) = $r;
|
|
|
|
$ok = mysqli_query($this->db,
|
|
"UPDATE " . TB_PREFIX . "alliance_bonus
|
|
SET level = level + 1, upgrade_end = 0
|
|
WHERE aid = " . $aid . " AND btype = " . $btype . "
|
|
AND upgrade_end > 0 AND upgrade_end <= " . $now . "
|
|
AND level < " . self::MAX_LEVEL . " LIMIT 1");
|
|
|
|
if ($ok && mysqli_affected_rows($this->db) > 0) {
|
|
$done++;
|
|
unset(self::$levelCache[$aid]);
|
|
$this->startUpgradeIfReady($aid, $btype);
|
|
}
|
|
}
|
|
|
|
return $done;
|
|
}
|
|
|
|
/** Contributia fiecarui membru, pentru afisare. */
|
|
public function contributions($aid, $limit = 30)
|
|
{
|
|
if (!self::enabled()) {
|
|
return array();
|
|
}
|
|
|
|
$aid = (int) $aid;
|
|
$limit = max(1, min(100, (int) $limit));
|
|
$out = array();
|
|
|
|
$res = mysqli_query($this->db,
|
|
"SELECT d.uid, u.username, SUM(d.amount) AS total
|
|
FROM " . TB_PREFIX . "alliance_donation_log d
|
|
LEFT JOIN " . TB_PREFIX . "users u ON u.id = d.uid
|
|
WHERE d.aid = " . $aid . "
|
|
GROUP BY d.uid, u.username
|
|
ORDER BY total DESC
|
|
LIMIT " . $limit);
|
|
|
|
while ($res && ($row = mysqli_fetch_assoc($res))) {
|
|
$out[] = array(
|
|
'uid' => (int) $row['uid'],
|
|
'username' => (string) $row['username'],
|
|
'total' => (float) $row['total'],
|
|
);
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Ajutor pentru hook-urile din joc */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
/**
|
|
* Multiplicatorul unui bonus pentru un jucator, ca numar (1.0 = fara bonus).
|
|
* Folosit de Technology, Battle, Market si Building.
|
|
*
|
|
* Rezultatul e cache-uit pe cerere: se cere de multe ori intr-o singura
|
|
* pagina (fiecare unitate din lista de instruire, fiecare val din lupta).
|
|
*/
|
|
public static function multiplier($uid, $btype)
|
|
{
|
|
static $cache = array();
|
|
|
|
$uid = (int) $uid;
|
|
$btype = (int) $btype;
|
|
$key = $uid . ':' . $btype;
|
|
|
|
if (isset($cache[$key])) {
|
|
return $cache[$key];
|
|
}
|
|
|
|
if (!self::enabled() || $uid <= 0) {
|
|
return $cache[$key] = 1.0;
|
|
}
|
|
|
|
$engine = new self();
|
|
$level = $engine->effectiveLevel($uid, $btype);
|
|
$pct = self::percentFor($btype, $level);
|
|
|
|
return $cache[$key] = 1.0 + ($pct / 100.0);
|
|
}
|
|
}
|