hujiabin 8f22573e97 1
2023-06-29 16:23:27 +08:00

681 lines
23 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace models;
require_once('mt/Hero.php');
require_once('mt/HeroLevelAttr.php');
require_once('mt/HeroQuality.php');
require_once('mt/HeroLevel.php');
require_once('mt/AttrHelper.php');
require_once('mt/Item.php');
require_once('models/HeroSkin.php');
require_once('models/Chip.php');
require_once('models/User.php');
require_once('models/ChipPlugin.php');
require_once('services/NftService.php');
require_once('services/FormulaService.php');
require_once('services/ContractConfig.php');
use mt;
use phpcommon;
use phpcommon\SqlHelper;
use services\NftService;
use services\FormulaService;
use services\ContractConfig;
use models\ChipPlugin;
use models\User;
class Hero extends BaseModel {
const GETED_STATE = 0;
const FREE_STATE = 1;
const NO_LOCK = 0;
const LEVEL_LOCK = 1;
const QUALITY_LOCK = 2;
const SEND_LOCK = 3;
const COST_LOCK = 4;
//需要材料所需等级
const LV_1 = 4;
const LV_2 = 9;
const LV_3 = 14;
public static function find($heroUniId)
{
return self::internalFind(myself()->_getAccountId(), myself()->_getAddress(), $heroUniId);
}
public static function findEx($heroUniId){
$row = SqlHelper::ormSelectOne(
myself()->_getMysql(myself()->_getAccountId()),
't_hero',
array(
'idx' => $heroUniId,
)
);
if ($row) {
if ($row['account_id'] != myself()->_getAccountId()) {
$row = null;
}
}
return $row;
}
public static function findByAccountId($accountId, $heroUniId)
{
return self::internalFind($accountId, User::findUserAddress($accountId), $heroUniId);
}
public static function findByTokenId($tokenId)
{
$row = SqlHelper::ormSelectOne(
myself()->_getMysql($tokenId),
't_hero',
array(
'token_id' => $tokenId,
)
);
if ($row) {
$row['hero_uniid'] = $row['idx'];
if (!NftService::isHeroOwner(myself()->_getAddress(), $row['token_id'])) {
$row = null;
}
}
return $row;
}
public static function findByTokenId2($tokenId)
{
$row = SqlHelper::ormSelectOne(
myself()->_getMysql($tokenId),
't_hero',
array(
'token_id' => $tokenId,
)
);
return $row;
}
private static function internalFind($accountId, $address, $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 = $address;
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) {
$row['tags'] = '';
$cb($row);
}
);
foreach (NftService::getHeros(myself()->_getAddress()) as $nftDb) {
if (! $nftDb['deleted']){
$row = SqlHelper::ormSelectOne(
myself()->_getSelfMysql(),
't_hero',
array(
'token_id' => $nftDb['token_id'],
)
);
//将NFT表的数据同步到中心化英雄表 (以后可能删除)
// 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) {
if (!$row['activate']) {
self::activateHero($row);
$row = SqlHelper::ormSelectOne(
myself()->_getSelfMysql(),
't_hero',
array(
'token_id' => $nftDb['token_id'],
)
);
}
$row['tags'] = $nftDb['tags'];
$cb($row);
}
}
}
}
private static function activateHero($row){
$itemMeta = mt\Item::get($row['hero_id']);
if (!$itemMeta) {
return;
}
// $randAttr = array();
$fieldsKv = array(
// 'hero_lv' => 1,
// 'quality' => 1,
// 'hero_tili' => 0,
// '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,
'activate' => 1,
'modifytime' => myself()->_getNowTime()
);
self::updateByTokenId($row['token_id'],$fieldsKv);
}
public static function toDto($row)
{
$attr = emptyReplace(json_decode($row['rand_attr'], true), array());
if (!$attr){
$heroMeta = mt\Hero::get($row['hero_id']);
$baseAttr = mt\Hero::getHeroAttr($heroMeta);
foreach ($baseAttr as $value){
if (in_array($value['attr_id'],array(kHAT_Hp,kHAT_Atk,kHAT_Def))){
array_push($attr,array(
'attr_id' => $value['attr_id'],
'val' => $value['val'] ,
'quality' => rand(2,3),
)
);
}else{
array_push($attr,array(
'attr_id' => $value['attr_id'],
'val' => $value['val'] ,
'quality' => 0,
)
);
}
}
self::update($row['idx'],array(
'rand_attr'=>json_encode($attr)
));
}
// $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'];
}
$levelMeta = mt\HeroLevel::getByLevel($row['hero_lv']);
$todayGetGold = $row['today_get_gold'];
$lastGetGoldTime = $row['last_get_gold_time'];
if (myself()->_getDaySeconds($lastGetGoldTime) <
myself()->_getNowDaySeconds()) {
$todayGetGold = 0;
}
$userDb = myself()->_getOrmUserInfo();
$isSelect = 0;
if ($row['idx'] == $userDb['hero_id']){
$isSelect = 1;
}
$skinDb = HeroSkin::findBx($row['hero_id']);
$dto = array(
'idx' => $row['idx'],
'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' => $skinDb?$skinDb['skin_id']:0,
'quality' => $row['quality'],
'skill_lv1' => $row['skill_lv1'],
'skill_lv2' => $row['skill_lv2'],
'rand_attr' => $attr,
'try_count' => $row['try_count'],
'lock_type' => $lockType,
'unlock_time' => $unlockTime,
'unlock_lefttime' => max(0,
$unlockTime - myself()->_getNowTime()),
'current_get_gold' => $todayGetGold / 100,
'last_get_gold_time' => $lastGetGoldTime,
'gold_uplimit' => $levelMeta['gold_limit'],
'unlock_trade_time' => $row['unlock_trade_time'],
'advanced_count' => $row['advanced_count'],
'offer_reward_state' => 0,
'tags' => isset($row['tags'])?$row['tags']:'',
'is_select' => $isSelect,
);
$nft_address = '';
$contract = ContractConfig::find(ContractConfig::ERC721);
if ($row['token_id']){
$nft_address = $contract ? $contract['hero'] : "";
}
$dto['nft_address'] = $nft_address;
return $dto;
}
public static function addFreeHero($heroMeta)
{
return self::internalAddHero(
myself()->_getSelfMysql(),
$heroMeta,
myself()->_getAccountId(),
null,
self::FREE_STATE);
}
public static function addHero($heroMeta)
{
return self::internalAddHero(
myself()->_getSelfMysql(),
$heroMeta,
myself()->_getAccountId(),
null,
self::GETED_STATE);
}
public static function addNftHero($heroMeta, $tokenId)
{
return self::internalAddHero(
myself()->_getMysql($tokenId),
$heroMeta,
null,
$tokenId,
self::GETED_STATE);
}
public static function internalAddHero($conn, $heroMeta, $accountId, $tokenId,$state)
{
$skinItemMeta = \mt\Item::getMetaListByType(\mt\Item::HERO_SKIN_TYPE);
if ($skinItemMeta){
foreach ($skinItemMeta as $value){
if ($value['playerid'] == $heroMeta['id'] && $value['isdefaultskin'] ==1){
HeroSkin::addSkin($value);
}
}
}
$realHeroMeta = mt\Hero::get($heroMeta['id']);
$randAttr = self::getRandAttr($heroMeta['id']) ;
$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' => $state,
'skill_lv1' => 1,
'skill_lv2' => 1,
'rand_attr' => json_encode($randAttr),
'lock_type' => self::NO_LOCK,
'unlock_time' => 0,
'unlock_trade_time' => 0,
'activate' => 1,
'base_attr' => json_encode($randAttr),
'createtime' => myself()->_getNowTime(),
'modifytime' => myself()->_getNowTime()
);
if ($accountId) {
$fieldsKv['account_id'] = $accountId;
}
if ($tokenId) {
$fieldsKv['token_id'] = $tokenId;
}
SqlHelper::insert(
$conn,
't_hero',
$fieldsKv
);
}
private static function getRandAttr($heroId){
$heroMeta = mt\Hero::get($heroId);
$baseAttr = mt\Hero::getHeroAttr($heroMeta);
$paramMeta = mt\Parameter::getVal('quality',0);
$attr = array();
if ($paramMeta){
$rate = explode('|',$paramMeta);
$minRate = $rate[0]*100;
$maxRate = $rate[count($rate)-1]*100;
foreach ($baseAttr as $value){
if (in_array($value['attr_id'],array(kHAT_Hp,kHAT_Atk,kHAT_Def))){
$finalRate = rand($minRate,$maxRate) / 100;
$quality = 0;
for ($i=0;$i<count($rate)-1;$i++){
if ($finalRate>=$rate[$i] && $finalRate<$rate[$i+1]){
$quality = $i+1;
}
if ($finalRate == $rate[count($rate)-1]){
$quality = count($rate)-1;
}
}
if ( $value['attr_id'] == kHAT_Hp){
$attr_val = round($value['val'] * $finalRate,0);
}else{
$attr_val = round($value['val'] * $finalRate,2);
}
array_push($attr,array(
'attr_id' => $value['attr_id'],
'val' => $attr_val,
'quality' => $quality,
// 'rate' => $finalRate,
)
);
} else {
array_push($attr,array(
'attr_id' => $value['attr_id'],
'val' => $value['val'] ,
'quality' => 0,
)
);
}
}
}
return $attr;
}
public static function update($heroUniId, $fieldsKv)
{
if (self::find($heroUniId)) {
SqlHelper::update
(myself()->_getSelfMysql(),
't_hero',
array(
'idx' => $heroUniId,
),
$fieldsKv
);
}
}
public static function updateByTokenId($tokenId, $fieldsKv)
{
if (self::findByTokenId($tokenId)) {
SqlHelper::update
(myself()->_getSelfMysql(),
't_hero',
array(
'token_id' => $tokenId,
),
$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 = null;
if (count($heroList)>0){
$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['gold_uplimit'],
$heroDto['current_get_gold'] + $addGold);
$finalyAddGold = max(0, $newGold - $heroDto['current_get_gold']);
// 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 gainGoldMission($heroDto, $addGold)
{
$newGold = min($heroDto['mission_ceg_uplimit'],
$heroDto['current_mission_get_ceg'] + $addGold);
$finalyAddGold = max(0, $newGold - $heroDto['current_mission_get_ceg']);
if ($finalyAddGold > 0) {
self::update($heroDto['hero_uniid'],
array(
'today_mission_get_ceg' => $newGold * 100,
'last_mission_get_ceg_time' => myself()->_getNowTime()
));
}
return $finalyAddGold;
}
public static function calcMissionGainGold($heroDto, $count)
{
if ($count <= 0) {
return 0;
}
$newGold = min($heroDto['mission_ceg_uplimit'],
$heroDto['current_mission_get_ceg'] +
$heroDto['mission_ceg_uplimit'] / $count);
$finalyAddGold = max(0, $newGold - $heroDto['current_mission_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;
}
public static function getFreeHero(){
$hero = array();
Hero::getHeroList(function ($row) use (&$hero) {
if (!$row['token_id']) {
$hero = $row;
}
});
return $hero;
}
public static function toDtoInfo($row){
$heroMeta = mt\Hero::get($row['hero_id']);
$attr = emptyReplace(json_decode($row['rand_attr'], true), array());
if ($attr){
foreach ($attr as &$value){
$value['val'] = floor($value['val']);
}
}else{
$attr = mt\Hero::getHeroAttr($heroMeta);
}
$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;
}
$heroLucky = \services\FormulaService::Hero_Advanced_Lucky_Value($row['quality']);
$info = array(
'idx' => $row['idx'],
'token_id' => $row['token_id'],
'hero_uniid' => $row['idx'],
'hero_name' => $heroMeta['name'],
'hero_id' => $row['hero_id'],
'hero_lv' => $row['hero_lv'],
'hero_tili' => $row['hero_tili'],
'quality' => $row['quality'],
'rand_attr' => $attr,
'current_pvp_get_ceg' => $todayGetGold / 100,
'current_pve_get_ceg' => $todayPveGetCeg / 100,
'advanced_count' => $row['advanced_count'],
'lucky' => strval($heroLucky),
'chip_ids' => $row['chip_ids'],
'chip_strength_sum' => strval(Chip::getChipMaxStrength($row['chip_ids'],1)), //计算ceg上限所需参数
'skill_points' => $row['skill_points'],
'labour' => $row['labour'],
);
$info['hero_tili_max'] = strval(round(FormulaService::Hero_NFT_Maximum_Physical_Strength($info['quality'],$info['lucky']),3));
$info['pvp_ceg_uplimit'] =strval( round(FormulaService::getHeroPvpDailyCegUpLimit($info),2) );
$info['pve_ceg_uplimit'] = strval( round(FormulaService::getHeroPveDailyCegUpLimit($info),2) );
return $info;
}
public static function getHeroByItemId($itemId){
$hero = array();
self::getHeroList(function ($row) use (&$hero,$itemId) {
if ($row['hero_id'] == $itemId) {
array_push($hero,$row);
}
});
return $hero;
}
public static function LvUpAddAttr($heroDb){
$randAttr = emptyReplace(json_decode($heroDb['rand_attr'], true), array());
$heroLevelMeta = \mt\HeroLevel::getByLevel($heroDb['hero_lv']+1);
$levelAttrMeta= \mt\HeroLevelAttr::find($heroDb['hero_id']);
// $attr= \mt\HeroLevelAttr::addRandAttr($levelAttrMeta,$type);
foreach ($randAttr as &$val){
if ($val['attr_id'] == kHAT_Def){
//升级后防御力:上一级防御力*((提升幅度+1^防御力系数)
$temp = $val['val'] * (pow(($heroLevelMeta['promote']+1),$levelAttrMeta['def_rate']));
$val['val'] = sprintf("%.2f",substr(sprintf("%.3f", $temp), 0, -1));
}else if( $val['attr_id'] == kHAT_Hp){
//升级后生命值:上一级生命值*((提升幅度+1^生命值系数)
$temp = $val['val'] * (pow(($heroLevelMeta['promote']+1),$levelAttrMeta['hp_rate']));
$val['val'] = sprintf("%.2f",substr(sprintf("%.3f", $temp), 0, -1));
}else if( $val['attr_id'] == kHAT_Atk){
//升级后攻击力:上一级攻击力*((提升幅度+1^攻击力系数)
$temp = $val['val'] * (pow(($heroLevelMeta['promote']+1),$levelAttrMeta['atk_rate']));
$val['val'] = sprintf("%.2f",substr(sprintf("%.3f", $temp), 0, -1));
}
}
return $randAttr;
}
}