545 lines
18 KiB
PHP
545 lines
18 KiB
PHP
<?php
|
|
|
|
namespace models;
|
|
|
|
require_once('mt/Hero.php');
|
|
require_once('mt/HeroLevelAttr.php');
|
|
require_once('mt/HeroQuality.php');
|
|
require_once('mt/AttrHelper.php');
|
|
require_once('mt/Item.php');
|
|
require_once('mt/SkillCommon.php');
|
|
require_once('models/HeroSkin.php');
|
|
require_once('models/Chip.php');
|
|
require_once('services/NftService.php');
|
|
require_once('services/FormulaService.php');
|
|
|
|
|
|
use mt;
|
|
use phpcommon;
|
|
use phpcommon\SqlHelper;
|
|
use services\NftService;
|
|
use services\FormulaService;
|
|
|
|
|
|
class Hero extends BaseModel {
|
|
|
|
const GETED_STATE = 0;
|
|
const TRY_STATE = 1;
|
|
|
|
const NO_LOCK = 0;
|
|
const LEVEL_LOCK = 1;
|
|
const QUALITY_LOCK = 2;
|
|
const SEND_LOCK = 3;
|
|
const COST_LOCK = 4;
|
|
|
|
public static function find($heroUniId)
|
|
{
|
|
return self::internalFind(myself()->_getAccountId(), $heroUniId);
|
|
}
|
|
|
|
public static function findByAccountId($accountId, $heroUniId)
|
|
{
|
|
return self::internalFind($accountId, $heroUniId);
|
|
}
|
|
|
|
private static function internalFind($accountId, $heroUniId)
|
|
{
|
|
$row = SqlHelper::ormSelectOne(
|
|
myself()->_getMysql($accountId),
|
|
't_hero',
|
|
array(
|
|
'idx' => $heroUniId,
|
|
)
|
|
);
|
|
if ($row) {
|
|
$row['hero_uniid'] = $row['idx'];
|
|
if ($row['account_id'] != $accountId) {
|
|
$openId = phpcommon\extractOpenId($accountId);
|
|
if (!NftService::isHeroOwner($openId, $row['token_id'])) {
|
|
$row = null;
|
|
}
|
|
}
|
|
}
|
|
return $row;
|
|
}
|
|
|
|
public static function getValidHero($heroId)
|
|
{
|
|
$heroList = array();
|
|
Hero::getHeroList(function ($row) use($heroId, &$heroList) {
|
|
if ($row['hero_id'] == $heroId && $row['state'] == self::GETED_STATE) {
|
|
array_push($heroList, Hero::toDto($row));
|
|
}
|
|
});
|
|
return !empty($heroList) ? $heroList[0] : null;
|
|
}
|
|
|
|
public static function getRawPveCegUpLimit()
|
|
{
|
|
$cegUpLimit = 0;
|
|
self::getHeroList(function ($row) use(&$cegUpLimit) {
|
|
$heroDto = self::toDto($row);
|
|
$cegUpLimit += $heroDto['raw_pve_ceg_uplimit'];
|
|
});
|
|
return $cegUpLimit;
|
|
}
|
|
|
|
public static function getHeroList($cb)
|
|
{
|
|
SqlHelper::ormSelect(
|
|
myself()->_getSelfMysql(),
|
|
't_hero',
|
|
array(
|
|
'account_id' => myself()->_getAccountId()
|
|
),
|
|
function ($row) use($cb) {
|
|
$cb($row);
|
|
}
|
|
);
|
|
foreach (NftService::getHeros(myself()->_getOpenId()) as $nftDb) {
|
|
if (! $nftDb['deleted']){
|
|
$row = SqlHelper::ormSelectOne(
|
|
myself()->_getSelfMysql(),
|
|
't_hero',
|
|
array(
|
|
'token_id' => $nftDb['token_id'],
|
|
)
|
|
);
|
|
if (!$row) {
|
|
$itemMeta = mt\Item::get($nftDb['item_id']);
|
|
if ($itemMeta) {
|
|
self::addNftHero($itemMeta, $nftDb['token_id']);
|
|
$row = SqlHelper::ormSelectOne(
|
|
myself()->_getSelfMysql(),
|
|
't_hero',
|
|
array(
|
|
'token_id' => $nftDb['token_id'],
|
|
)
|
|
);
|
|
}
|
|
}
|
|
if ($row) {
|
|
$cb($row);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function toDto($row)
|
|
{
|
|
$attr = emptyReplace(json_decode($row['rand_attr'], true), array());
|
|
|
|
$lockType = 0;
|
|
$unlockTime = 0;
|
|
/*if ($row['lock_type'] != 0 && $row['unlock_time'] - myself()->_getNowTime() > 0) {
|
|
$lockType = $row['lock_type'];
|
|
$unlockTime = $row['unlock_time'];
|
|
}*/
|
|
{
|
|
$lockType = $row['lock_type'];
|
|
$unlockTime = $row['unlock_time'];
|
|
}
|
|
|
|
$qualityMeta = mt\HeroQuality::getByQuality($row['quality']);
|
|
$todayGetGold = $row['today_get_gold'];
|
|
$lastGetGoldTime = $row['last_get_gold_time'];
|
|
if (myself()->_getDaySeconds($lastGetGoldTime) <
|
|
myself()->_getNowDaySeconds()) {
|
|
$todayGetGold = 0;
|
|
}
|
|
$todayPveGetCeg = $row['today_pve_get_ceg'];
|
|
$lastPveGetCegTime = $row['last_pve_get_ceg_time'];
|
|
if (myself()->_getDaySeconds($lastPveGetCegTime) <
|
|
myself()->_getNowDaySeconds()) {
|
|
$todayPveGetCeg = 0;
|
|
}
|
|
$baseAttr=[];
|
|
$attrPro=[];
|
|
$heroMeta = mt\Hero::get($row['hero_id']);
|
|
if ($heroMeta) {
|
|
$baseAttr = mt\Hero::getHeroAttr($heroMeta);
|
|
$attrPro1=[];
|
|
if ($row['hero_lv']>1){
|
|
$attrPro1 = self::getAttrProByLevel($row,$baseAttr,$attr);
|
|
}
|
|
$attrPro2=[];
|
|
if ($row['quality']>1){
|
|
$attrPro2 = self::getAttrProByQuality($row,$baseAttr);
|
|
}
|
|
$attrPro = self::mergeAttrPro($baseAttr,$attrPro1,$attrPro2);
|
|
}
|
|
//print_r($attr);die;
|
|
$skill_common = explode("|",$row['skill_common']);
|
|
$attr_skill = [];
|
|
foreach ($skill_common as $val){
|
|
$item = mt\SkillCommon::getAttrBySkillCommon($val);
|
|
if ($item){
|
|
array_push($attr_skill,$item);
|
|
}
|
|
}
|
|
$heroLucky = \services\FormulaService::Hero_Advanced_Lucky_Value($row['quality']);
|
|
$dto = array(
|
|
'token_id' => $row['token_id'],
|
|
'hero_uniid' => $row['idx'],
|
|
'hero_id' => $row['hero_id'],
|
|
'hero_lv' => $row['hero_lv'],
|
|
'hero_tili' => $row['hero_tili'],
|
|
'state' => $row['state'],
|
|
'skin_id' => $row['skin_id'],
|
|
'quality' => $row['quality'],
|
|
'skill_lv1' => $row['skill_lv1'],
|
|
'skill_lv2' => $row['skill_lv2'],
|
|
'attr_base' => $baseAttr,
|
|
'attr_pro' => $attrPro,
|
|
'attr_skill' => $attr_skill,
|
|
'attr_chip' => Chip::getChipAttr($row['chip_ids'])['attr_chip'],
|
|
'chip_core' => Chip::getChipAttr($row['chip_ids'])['chip_core'],
|
|
'try_count' => $row['try_count'],
|
|
'lock_type' => $lockType,
|
|
'unlock_time' => $unlockTime,
|
|
'unlock_lefttime' => max(0,
|
|
$unlockTime - myself()->_getNowTime()),
|
|
'current_pvp_get_ceg' => $todayGetGold / 100,
|
|
'last_pvp_get_ceg_time' => $lastGetGoldTime,
|
|
'current_pve_get_ceg' => $todayPveGetCeg / 100,
|
|
'last_pve_get_ceg_time' => $lastPveGetCegTime,
|
|
'unlock_trade_time' => $row['unlock_trade_time'],
|
|
'advanced_count' => $row['advanced_count'],
|
|
'lucky' => $heroLucky,
|
|
'chip_ids' => $row['chip_ids'],
|
|
'chip_strength_sum' => strval(Chip::getChipMaxStrength($row['chip_ids'],1)), //计算ceg上限所需参数
|
|
'skill_common' => $skill_common,
|
|
'skill_points' => $row['skill_points'],
|
|
'offer_reward_state' => 0,
|
|
);
|
|
$dto['hero_tili_max'] = strval(round(FormulaService::Hero_NFT_Maximum_Physical_Strength($dto['quality'],$dto['lucky']),3));
|
|
$dto['pvp_ceg_uplimit'] =strval( round(FormulaService::getHeroPvpDailyCegUpLimit($dto),2) );
|
|
$dto['pve_ceg_uplimit'] = strval( round(FormulaService::getHeroPveDailyCegUpLimit($dto),2) );
|
|
|
|
return $dto;
|
|
}
|
|
|
|
public static function addHero($heroMeta)
|
|
{
|
|
return self::internalAddHero(
|
|
myself()->_getSelfMysql(),
|
|
$heroMeta,
|
|
myself()->_getAccountId(),
|
|
null);
|
|
}
|
|
|
|
public static function addNftHero($heroMeta, $tokenId)
|
|
{
|
|
return self::internalAddHero(
|
|
myself()->_getMysql($tokenId),
|
|
$heroMeta,
|
|
null,
|
|
$tokenId);
|
|
}
|
|
|
|
public static function internalAddHero($conn, $heroMeta, $accountId, $tokenId)
|
|
{
|
|
$realHeroMeta = mt\Hero::get($heroMeta['id']);
|
|
$randAttr = array();
|
|
$fieldsKv = array(
|
|
'hero_id' => $heroMeta['id'],
|
|
'hero_lv' => 1,
|
|
'quality' => 1,
|
|
'hero_tili' => FormulaService::Hero_NFT_Maximum_Physical_Strength(1,FormulaService::Hero_Advanced_Lucky_Value(1)),
|
|
'state' => self::GETED_STATE,
|
|
'skill_lv1' => 1,
|
|
'skill_lv2' => 1,
|
|
'rand_attr' => json_encode($randAttr),
|
|
'lock_type' => self::NO_LOCK,
|
|
'unlock_time' => 0,
|
|
'unlock_trade_time' => 0,
|
|
'skill_points' => 0,
|
|
'createtime' => myself()->_getNowTime(),
|
|
'modifytime' => myself()->_getNowTime()
|
|
);
|
|
if ($accountId) {
|
|
$fieldsKv['account_id'] = $accountId;
|
|
}
|
|
if ($tokenId) {
|
|
$fieldsKv['token_id'] = $tokenId;
|
|
}
|
|
|
|
SqlHelper::insert(
|
|
myself()->_getSelfMysql(),
|
|
't_hero',
|
|
$fieldsKv
|
|
);
|
|
}
|
|
|
|
public static function addTryHero($heroMeta, $tryCount)
|
|
{
|
|
$realHeroMeta = mt\Hero::get($heroMeta['id']);
|
|
$randAttr = array();
|
|
{
|
|
$initQualityMeta = mt\HeroQuality::getByQuality(1);
|
|
if ($initQualityMeta) {
|
|
$randAttr = mt\HeroQuality::getRandAttr($initQualityMeta);
|
|
}
|
|
}
|
|
SqlHelper::upsert(
|
|
myself()->_getSelfMysql(),
|
|
't_hero',
|
|
array(
|
|
'account_id' => myself()->_getAccountId(),
|
|
'hero_id' => $heroMeta['id']
|
|
),
|
|
array(
|
|
),
|
|
array(
|
|
'account_id' => myself()->_getAccountId(),
|
|
'hero_id' => $heroMeta['id'],
|
|
'hero_lv' => 1,
|
|
'quality' => 1,
|
|
'hero_tili' => $realHeroMeta ? $realHeroMeta['tili'] : 0,
|
|
'state' => self::TRY_STATE,
|
|
'try_count' => $tryCount,
|
|
'skill_lv1' => 1,
|
|
'skill_lv2' => 1,
|
|
'rand_attr' => json_encode($randAttr),
|
|
'lock_type' => self::NO_LOCK,
|
|
'unlock_time' => 0,
|
|
'unlock_trade_time' => 0,
|
|
'createtime' => myself()->_getNowTime(),
|
|
'modifytime' => myself()->_getNowTime()
|
|
)
|
|
);
|
|
}
|
|
|
|
public static function takeonSkin($heroUniId, $skinId)
|
|
{
|
|
self::update($heroUniId, array(
|
|
'skin_id' => $skinId,
|
|
'modifytime' => myself()->_getNowTime()
|
|
));
|
|
}
|
|
|
|
public static function upgradeSkill($heroUniId, $skillIdx)
|
|
{
|
|
if (!in_array($skillIdx, array(0, 1))) {
|
|
return;
|
|
}
|
|
$fieldName = 'skill_lv' . ($skillIdx + 1);
|
|
self::update($heroUniId, array(
|
|
$fieldName => function () use($fieldName) {
|
|
return "${fieldName} + 1";
|
|
},
|
|
'modifytime' => myself()->_getNowTime()
|
|
));
|
|
}
|
|
|
|
public static function update($heroUniId, $fieldsKv)
|
|
{
|
|
if (self::find($heroUniId)) {
|
|
SqlHelper::update
|
|
(myself()->_getSelfMysql(),
|
|
't_hero',
|
|
array(
|
|
'idx' => $heroUniId,
|
|
),
|
|
$fieldsKv
|
|
);
|
|
}
|
|
}
|
|
|
|
public static function randHero(&$heroUniId, &$heroId)
|
|
{
|
|
$heroUniId = 0;
|
|
$heroId = 0;
|
|
|
|
$heroList = array();
|
|
Hero::getHeroList(function ($row) use($heroId, &$heroList) {
|
|
if ($row['state'] == self::GETED_STATE) {
|
|
array_push($heroList, Hero::toDto($row));
|
|
}
|
|
});
|
|
|
|
$key = array_rand($heroList, 1);
|
|
if (!is_null($key)) {
|
|
$heroUniId = $heroList[$key]['idx'];
|
|
$heroId = $heroList[$key]['hero_id'];
|
|
}
|
|
}
|
|
|
|
public static function addTili($heroUniId, $tili)
|
|
{
|
|
self::update($heroUniId,
|
|
array(
|
|
'hero_tili' => function () use($tili) {
|
|
return "hero_tili + ${tili}";
|
|
},
|
|
));
|
|
}
|
|
|
|
public static function gainGoldPvp($heroDto, $addGold)
|
|
{
|
|
$newGold = min($heroDto['pvp_ceg_uplimit'],
|
|
$heroDto['current_pvp_get_ceg'] + $addGold);
|
|
$finalyAddGold = max(0, $newGold - $heroDto['current_pvp_get_ceg']);
|
|
if ($finalyAddGold > 0) {
|
|
self::update($heroDto['hero_uniid'],
|
|
array(
|
|
'today_get_gold' => $newGold * 100,
|
|
'last_get_gold_time' => myself()->_getNowTime()
|
|
));
|
|
}
|
|
return $finalyAddGold;
|
|
}
|
|
|
|
public static function gainGoldPve($heroDto, $addGold)
|
|
{
|
|
$newGold = min($heroDto['pve_ceg_uplimit'],
|
|
$heroDto['current_pve_get_ceg'] + $addGold);
|
|
$finalyAddGold = max(0, $newGold - $heroDto['current_pve_get_ceg']);
|
|
if ($finalyAddGold > 0) {
|
|
self::update($heroDto['hero_uniid'],
|
|
array(
|
|
'today_pve_get_ceg' => $newGold * 100,
|
|
'last_pve_get_ceg_time' => myself()->_getNowTime()
|
|
));
|
|
}
|
|
return $finalyAddGold;
|
|
}
|
|
|
|
public static function calcPveGainGold($heroDto, $count)
|
|
{
|
|
if ($count <= 0) {
|
|
return 0;
|
|
}
|
|
$newGold = min($heroDto['pve_ceg_uplimit'],
|
|
$heroDto['today_pve_get_ceg'] +
|
|
round($heroDto['pve_ceg_uplimit'] / $count));
|
|
$finalyAddGold = max(0, $newGold - $heroDto['today_pve_get_ceg']);
|
|
return $finalyAddGold;
|
|
}
|
|
|
|
public static function heroIsLocking($heroDto)
|
|
{
|
|
if ($heroDto['lock_type']) {
|
|
return true;
|
|
}
|
|
$locking = false;
|
|
$heroUniId = !empty($heroDto['hero_uniid']) ? $heroDto['hero_uniid'] : $heroDto['idx'];
|
|
{
|
|
$idx = 0;
|
|
for ($i = 0; $i < kMaxHeroUpQualityNum; ++$i) {
|
|
$upHeroUniId = myself()->_getV(TN_HERO_QUALITY_UP, $i);
|
|
if ($upHeroUniId == $heroUniId) {
|
|
$idx = $i;
|
|
$locking = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!$locking) {
|
|
$idx = 0;
|
|
for ($i = 0; $i < kMaxHeroUpLevelNum; ++$i) {
|
|
$upHeroUniId = myself()->_getV(TN_HERO_LEVEL_UP, $i);
|
|
if ($upHeroUniId == $heroUniId) {
|
|
$idx = $i;
|
|
$locking = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return $locking;
|
|
}
|
|
|
|
private static function mergeAttrPro($baseAttr,$attrPro1,$attrPro2){
|
|
$newAttr = [];
|
|
$newAttrPro = [];
|
|
if ($attrPro1 && !$attrPro2){
|
|
$newAttrPro = $attrPro1;
|
|
}
|
|
if (!$attrPro1 && $attrPro2){
|
|
$newAttrPro = $attrPro2;
|
|
}
|
|
if ($attrPro1 && $attrPro2){
|
|
foreach ($attrPro1 as $value){
|
|
foreach ($attrPro2 as $val){
|
|
if ($value['attr_id'] == $val['attr_id']){
|
|
array_push($newAttr,
|
|
[
|
|
'attr_id' => $value['attr_id'],
|
|
'type' => $value['type'],
|
|
'val' => $value['val']+$val['val'],
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
if ($newAttr){
|
|
foreach ($baseAttr as $value){
|
|
foreach ($newAttr as $val){
|
|
if ($value['attr_id'] == $val['attr_id']){
|
|
array_push($newAttrPro,
|
|
[
|
|
'attr_id' => $value['attr_id'],
|
|
'type' => $value['type'],
|
|
'val' => strval($val['val']-$value['val']),
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $newAttrPro;
|
|
}
|
|
|
|
private static function getAttrProByLevel($row,$baseAttr,$attr){
|
|
$attrPro1 = [];
|
|
$coefficient_level = mt\HeroLevelAttr::getCoefficientByLevel($row['hero_lv'],$row['hero_id']);
|
|
foreach ($baseAttr as $val){
|
|
$coef_level = mt\HeroLevelAttr::getByCoefficient($coefficient_level,$val['attr_id']);
|
|
foreach ($attr as $v){
|
|
if ($val['attr_id'] == $v['attr_id'] && $val['attr_id'] == kHAT_Atk){ //18 //18.941564456287 //20.847692307692
|
|
array_push($attrPro1,[
|
|
'attr_id' => $val['attr_id'],
|
|
'type'=> $val['type'],
|
|
'val' => strval($val['val']*$v['val']+$v['val']/$coef_level['val']*100-100/$coef_level['val']),
|
|
]);
|
|
}
|
|
if ($val['attr_id'] == $v['attr_id'] && $val['attr_id'] != kHAT_Atk){
|
|
array_push($attrPro1,[
|
|
'attr_id' => $val['attr_id'],
|
|
'type'=> $val['type'],
|
|
'val' => strval($val['val']*pow($v['val'],$coef_level['val'])),
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
return $attrPro1;
|
|
}
|
|
|
|
private static function getAttrProByQuality($row,$baseAttr){
|
|
$attrPro2 = [];
|
|
$qualityMeta = mt\HeroQuality::getByQuality($row['quality']);
|
|
$coefficient_quality = mt\HeroQuality::getCoefficientByQuality($row['quality'],$row['hero_id']);
|
|
foreach ($baseAttr as $val){
|
|
$coef_quality = mt\HeroQuality::getByCoefficient($coefficient_quality,$val['attr_id']);
|
|
if ($coef_quality){
|
|
if ($val['attr_id'] == kHAT_Atk){
|
|
array_push($attrPro2,[
|
|
'attr_id' => $val['attr_id'],
|
|
'type'=> $val['type'],
|
|
'val' => strval($val['val']*$qualityMeta['promote_val']+$qualityMeta['promote_val']/$coef_quality['val']*100-100/$coef_quality['val']),
|
|
]);
|
|
}
|
|
if ($val['attr_id'] != kHAT_Atk) {
|
|
array_push($attrPro2, [
|
|
'attr_id' => $val['attr_id'],
|
|
'type' => $val['type'],
|
|
'val' => strval($val['val'] * pow($qualityMeta['promote_val'], $coef_quality['val'])),
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
return $attrPro2;
|
|
}
|
|
|
|
|
|
}
|