diff --git a/GameEngine/Data/hero_items.php b/GameEngine/Data/hero_items.php
index 717362d0..4d4fff93 100644
--- a/GameEngine/Data/hero_items.php
+++ b/GameEngine/Data/hero_items.php
@@ -342,8 +342,8 @@ $heroAdventureConfig = array(
'silver' => array(0, 40),
'hp_loss' => array(0, 8),
'resources' => array(0, 400),
- 'equip_chance' => 3, // % chance: 1 random piece of gear
- 'item_chance' => 5, // % chance: consumables (rolled only if no gear dropped)
+ 'equip_chance' => 20, // % chance: 1 random piece of gear
+ 'item_chance' => 40, // % chance: consumables (rolled only if no gear dropped)
'consumable' => array(200, 201, 208), // Ointment, Scroll, Cage
),
1 => array( // HARD
diff --git a/GameEngine/Lang/en.php b/GameEngine/Lang/en.php
index 27283f74..47610019 100755
--- a/GameEngine/Lang/en.php
+++ b/GameEngine/Lang/en.php
@@ -4394,3 +4394,11 @@ tz_def('SITTER_P_GOLD', 'spend Gold');
tz_def('SITTER_P_DENIED', 'Your sitter permissions do not allow this action.');
tz_def('SITTER_P_HINT', 'Permissions for the new sitter:');
tz_def('SITTER_P_NOT_SITTING', 'You are not a sitter on any account.');
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// REDUCERI TIMP INSTRUIRE (cazarma / grajd)
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+tz_def('TRAIN_BONUS_ARTIFACT', 'Artifact bonus');
+tz_def('TRAIN_BONUS_HERO', 'Hero bonus');
+tz_def('TRAIN_BONUS_ALLIANCE', 'Alliance bonus');
+tz_def('TRAIN_BONUS_FINAL', 'Training time');
diff --git a/GameEngine/Lang/fr.php b/GameEngine/Lang/fr.php
index f6446376..4d32fc1a 100644
--- a/GameEngine/Lang/fr.php
+++ b/GameEngine/Lang/fr.php
@@ -4336,4 +4336,12 @@ tz_def('SITTER_P_RES', 'envoyer des ressources à d’autres joueurs');
tz_def('SITTER_P_GOLD', 'dépenser de l’or');
tz_def('SITTER_P_DENIED', 'Vos permissions de sitter ne vous permettent pas d’effectuer cette action.');
tz_def('SITTER_P_HINT', 'Permissions du nouveau sitter :');
-tz_def('SITTER_P_NOT_SITTING', 'Vous n\'etes sitter sur aucun compte.');
\ No newline at end of file
+tz_def('SITTER_P_NOT_SITTING', 'Vous n\'etes sitter sur aucun compte.');
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// RÉDUCTIONS DU TEMPS D'ENTRAÎNEMENT (caserne / écurie)
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+tz_def('TRAIN_BONUS_ARTIFACT', 'Bonus artefact');
+tz_def('TRAIN_BONUS_HERO', 'Bonus héros');
+tz_def('TRAIN_BONUS_ALLIANCE', 'Bonus alliance');
+tz_def('TRAIN_BONUS_FINAL', 'Temps d’entraînement');
\ No newline at end of file
diff --git a/GameEngine/Lang/ro.php b/GameEngine/Lang/ro.php
index dbe259fa..18eaaf4a 100644
--- a/GameEngine/Lang/ro.php
+++ b/GameEngine/Lang/ro.php
@@ -4131,4 +4131,12 @@ tz_def('SITTER_P_RES', 'trimite resurse altor jucatori');
tz_def('SITTER_P_GOLD', 'cheltuie aur');
tz_def('SITTER_P_DENIED', 'Permisiunile tale de sitter nu iti permit aceasta actiune.');
tz_def('SITTER_P_HINT', 'Permisiuni pentru noul sitter:');
-tz_def('SITTER_P_NOT_SITTING', 'Nu esti sitter pe niciun cont.');
\ No newline at end of file
+tz_def('SITTER_P_NOT_SITTING', 'Nu esti sitter pe niciun cont.');
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// REDUCERI TIMP INSTRUIRE (cazarma / grajd)
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+tz_def('TRAIN_BONUS_ARTIFACT', 'Bonus artefact');
+tz_def('TRAIN_BONUS_HERO', 'Bonus erou');
+tz_def('TRAIN_BONUS_ALLIANCE', 'Bonus alianta');
+tz_def('TRAIN_BONUS_FINAL', 'Timp instruire');
\ No newline at end of file
diff --git a/GameEngine/Technology.php b/GameEngine/Technology.php
index 24d60d08..01155259 100755
--- a/GameEngine/Technology.php
+++ b/GameEngine/Technology.php
@@ -655,6 +655,13 @@ class Technology {
// in cazarma/grajd normale si in cele mari (Great Barracks/Great Stable),
// fiindca ramura e aleasa dupa TIPUL unitatii, nu dupa cladire.
// Nu se aplica la atelier, unitati speciale sau capcane - la fel ca in T4.
+ // FIX: artefactele de instruire (kind 5) erau aplicate DOAR la afisare,
+ // in sabloane - trainUnit() nu le folosea deloc. Un jucator cu artefact
+ // vedea jumatate din timp, dar trupele se antrenau in timpul intreg.
+ // Se aplica pe timpul dat de cladire, inaintea bonusurilor de erou si
+ // alianta, exact in ordinea in care sabloanele afisau pana acum.
+ $each = $this->applyArtifactTrainingBonus($each);
+
$each = $this->applyHeroTrainingBonus($each, $unit, $footies, $calvary);
// Bonusul de alianta "Recruitment": instruire mai rapida in toate
@@ -665,6 +672,199 @@ class Technology {
return $each;
}
+ /**
+ * Defalcarea reducerilor de timp pentru afisare in cazarma / grajd.
+ *
+ * Primeste timpul de baza pe care sablonul l-a calculat deja (formula
+ * cladirii + artefacte) si intoarce cum arata el dupa fiecare bonus:
+ *
+ * 'hero_percent' - % dat de coiful eroului (0 daca nu are)
+ * 'after_hero' - timpul dupa bonusul eroului
+ * 'hero_saved' - secunde economisite de erou
+ * 'alliance_percent' - % dat de bonusul de alianta Recruitment
+ * 'after_alliance' - timpul final
+ * 'alliance_saved' - secunde economisite de alianta
+ * 'total_saved' - economia totala
+ * 'has_bonus' - true daca exista cel putin o reducere
+ *
+ * Refoloseste EXACT aceleasi doua metode private pe care le apeleaza si
+ * getTrainingTime(), in aceeasi ordine (erou, apoi alianta). Asa afisajul
+ * nu poate ajunge sa spuna altceva decat calculeaza motorul: daca cineva
+ * schimba candva formula, se schimba in amandoua locurile deodata.
+ */
+ public function getTrainingBonusInfo($unit, $baseTime) {
+
+ $footies = [1, 2, 3, 11, 12, 13, 14, 21, 22, 31, 32, 33, 34, 41, 42, 43, 44, 51, 52, 61, 62, 63, 71, 72, 73, 74, 81, 82, 83, 84];
+ $calvary = [4, 5, 6, 15, 16, 23, 24, 25, 26, 35, 36, 45, 46, 53, 54, 55, 56, 64, 65, 66, 75, 76, 85, 86];
+
+ $baseTime = (int) $baseTime;
+
+ $info = array(
+ 'base' => $baseTime,
+ 'artifact_percent' => 0,
+ 'after_artifact' => $baseTime,
+ 'artifact_saved' => 0,
+ 'hero_percent' => 0,
+ 'after_hero' => $baseTime,
+ 'hero_saved' => 0,
+ 'alliance_percent' => 0,
+ 'after_alliance' => $baseTime,
+ 'alliance_saved' => 0,
+ 'total_saved' => 0,
+ 'has_bonus' => false,
+ );
+
+ if ($baseTime <= 0) {
+ return $info;
+ }
+
+ /**
+ * IMPORTANT: procentele se iau din SURSA bonusului, nu din secundele
+ * economisite.
+ *
+ * Pe serverele rapide (100x) timpii ajung la 1-4 secunde, iar o
+ * reducere de 8% din 2 secunde inseamna 0,15s - care dispare la
+ * rotunjirea la secunda intreaga. Calculat din secunde, bonusul de
+ * alianta parea inexistent, desi el se aplica. Procentul nominal e
+ * mereu corect, iar secundele economisite raman doar informative.
+ */
+
+ // --- artefacte ---
+ $info['artifact_percent'] = $this->artifactTrainingPercent();
+ $afterArtifact = $this->applyArtifactTrainingBonus($baseTime);
+ $info['after_artifact'] = $afterArtifact;
+ $info['artifact_saved'] = $baseTime - $afterArtifact;
+
+ // --- coiful eroului ---
+ $info['hero_percent'] = $this->heroTrainingPercent($unit, $footies, $calvary);
+ $afterHero = $this->applyHeroTrainingBonus($afterArtifact, $unit, $footies, $calvary);
+ $info['after_hero'] = $afterHero;
+ $info['hero_saved'] = $afterArtifact - $afterHero;
+
+ // --- bonusul de alianta ---
+ $info['alliance_percent'] = $this->allianceTrainingPercent();
+ $afterAlliance = $this->applyAllianceRecruitmentBonus($afterHero);
+ $info['after_alliance'] = $afterAlliance;
+ $info['alliance_saved'] = $afterHero - $afterAlliance;
+
+ $info['total_saved'] = $baseTime - $afterAlliance;
+
+ $info['has_bonus'] = ($info['artifact_percent'] > 0
+ || $info['hero_percent'] > 0
+ || $info['alliance_percent'] > 0);
+
+ return $info;
+ }
+
+ /**
+ * Procentul de reducere dat de artefacte, dedus din chiar functia care il
+ * aplica: o valoare mare trece prin ea, iar raportul da procentul. Asa nu
+ * duplicam logica multiplicatorilor si a "artefactului nebunului".
+ */
+ private function artifactTrainingPercent() {
+
+ $probe = 1000000;
+ $out = $this->applyArtifactTrainingBonus($probe);
+
+ if ($out >= $probe) {
+ return 0;
+ }
+
+ return (int) round(($probe - $out) * 100 / $probe);
+ }
+
+ /** Procentul dat de coiful echipat al eroului (0 daca nu are). */
+ private function heroTrainingPercent($unit, array $footies, array $calvary) {
+ global $village, $database;
+
+ if (!class_exists('HeroBattleBonus') || !HeroBattleBonus::enabled()) {
+ return 0;
+ }
+
+ $uid = (isset($village->wid) && $database)
+ ? (int) $database->getVillageField($village->wid, 'owner')
+ : 0;
+
+ if ($uid <= 0) {
+ return 0;
+ }
+
+ $bonuses = HeroBattleBonus::bonuses($uid);
+
+ if (!$bonuses) {
+ return 0;
+ }
+
+ if (in_array($unit, $footies)) {
+ $percent = (int) $bonuses[HB_TRAIN_INF];
+ } elseif (in_array($unit, $calvary)) {
+ $percent = (int) $bonuses[HB_TRAIN_CAV];
+ } else {
+ return 0;
+ }
+
+ if ($percent < 0) $percent = 0;
+ if ($percent > 90) $percent = 90;
+
+ return $percent;
+ }
+
+ /**
+ * Procentul efectiv al bonusului de alianta "Recruitment".
+ *
+ * Bonusul e multiplicativ (timpul se imparte la 1+x), deci un bonus
+ * anuntat ca +8% inseamna 1 - 1/1.08 = 7% timp mai putin. Afisam procentul
+ * real de reducere, nu pe cel din panoul aliantei.
+ */
+ private function allianceTrainingPercent() {
+ global $village, $database;
+
+ if (!class_exists('AllianceBonus') || !AllianceBonus::enabled()) {
+ return 0;
+ }
+
+ $owner = (isset($village->wid) && $database)
+ ? (int) $database->getVillageField($village->wid, 'owner')
+ : 0;
+
+ if ($owner <= 0) {
+ return 0;
+ }
+
+ $mult = AllianceBonus::multiplier($owner, AllianceBonus::RECRUITMENT);
+
+ if ($mult <= 1.0) {
+ return 0;
+ }
+
+ return (int) round((1 - (1 / $mult)) * 100);
+ }
+
+ /**
+ * Aplica influenta artefactelor de instruire (kind 5) asupra timpului.
+ *
+ * Proprietarul si satul se iau la fel ca la celelalte doua bonusuri, ca sa
+ * fie corect si cand codul ruleaza in alt context (cron, sitter, admin).
+ */
+
+ private function applyArtifactTrainingBonus($each) {
+ global $village, $database;
+
+ if (!$database || !isset($village->wid)) {
+ return $each;
+ }
+
+ $uid = (int) $database->getVillageField($village->wid, 'owner');
+
+ if ($uid <= 0) {
+ return $each;
+ }
+
+ $out = (int) $database->getArtifactsValueInfluence($uid, $village->wid, 5, $each);
+
+ return $out > 0 ? $out : 1;
+ }
+
/**
* Aplica bonusul de alianta "Recruitment" asupra timpului de instruire.
*
diff --git a/Templates/Build/19_train.tpl b/Templates/Build/19_train.tpl
index fafeefc3..dd4c2d35 100644
--- a/Templates/Build/19_train.tpl
+++ b/Templates/Build/19_train.tpl
@@ -35,12 +35,13 @@ foreach ($units as $i) {
$maxPlus = $technology->maxUnitPlus($i);
$available = (int)($village->unitarray['u'.$i] ?? 0);
- $dur = $database->getArtifactsValueInfluence(
- $session->uid,
- $village->wid,
- 5,
- round($unitData['time'] * ($bid19[$village->resarray['f'.$id]]['attri'] / 100) / SPEED)
- );
+ /**
+ * Timpul de BAZA, doar din formula cladirii. Artefactele nu se mai aplica
+ * aici: sunt tratate ca reducere, alaturi de erou si alianta, in
+ * train_bonus.tpl - si, din acest commit, si in motor (Technology.php),
+ * unde inainte lipseau cu totul.
+ */
+ $dur = (int) round($unitData['time'] * ($bid19[$village->resarray['f'.$id]]['attri'] / 100) / SPEED);
$timeFormatted = $generator->getTimeFormat($dur);
$total_required = (int)($unitData['wood'] + $unitData['clay'] + $unitData['iron'] + $unitData['crop']);
@@ -64,6 +65,12 @@ foreach ($units as $i) {
|
+
+
+
+
+
+
+
+
+
+
+ getTimeFormat($tbInfo['after_alliance']); ?>
+
+