_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::TYPE_FREE); } public static function addHero1($heroMeta) { return self::internalAddHero( myself()->_getSelfMysql(), $heroMeta, myself()->_getAccountId(), null, self::TYPE_1); } public static function addHero2($heroMeta) { return self::internalAddHero( myself()->_getSelfMysql(), $heroMeta, myself()->_getAccountId(), null, self::TYPE_2); } public static function addHero3($heroMeta) { return self::internalAddHero( myself()->_getSelfMysql(), $heroMeta, myself()->_getAccountId(), null, self::TYPE_3); } public static function addHero($heroMeta) { return self::internalAddHero( myself()->_getSelfMysql(), $heroMeta, myself()->_getAccountId(), null, self::TYPE_4); } 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,$type) { $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); } } } $state = $type > 0 ? self::GETED_STATE : self::FREE_STATE; $realHeroMeta = mt\Hero::get($heroMeta['id']); $randAttr = self::getRandAttr($heroMeta['id'],$type) ; $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 ); return true; } private static function _getAttrQuality($type){ $quality = 0; switch ($type){ case self::TYPE_FREE :{ $quality = 1; }break; case self::TYPE_1 :{ $paramMeta = mt\Parameter::getVal('small_box_quality',0); }break; case self::TYPE_2 :{ $paramMeta = mt\Parameter::getVal('big_box_quality',0); }break; case self::TYPE_3 :{ $paramMeta = mt\Parameter::getVal('super_box_quality',0); }break; case self::TYPE_4 :{ $paramMeta = mt\Parameter::getVal('buy_hero_quality',0); }break; default:{ $quality = 1; } } if (isset($paramMeta)){ $weightArr = explode("|",$paramMeta); $totalWeight = 0; foreach ($weightArr as $value){ $weights = explode(":",$value); $totalWeight += $weights[1]; } $currWeight = 0; $rnd = rand() % $totalWeight; foreach ($weightArr as $value){ $weights = explode(":",$value); $currWeight += $weights[1]; if ($currWeight > $rnd) { $quality = $weights[0]; break; } } } return $quality; } private static function getRandAttr($heroId,$type){ $heroMeta = mt\Hero::get($heroId); $baseAttr = mt\Hero::getHeroAttr($heroMeta); $paramMeta = mt\Parameter::getVal('quality',0); $attr = array(); if ($paramMeta){ $rate = explode('|',$paramMeta); foreach ($baseAttr as $value){ if (in_array($value['attr_id'],array(kHAT_Hp,kHAT_Atk,kHAT_Def))){ $quality = self::_getAttrQuality($type); $minRate = $rate[$quality-1] * 100; $maxRate = $rate[$quality] * 100 - 1; if ($quality == 5){ $maxRate = $rate[$quality] * 100; } $finalRate = rand($minRate,$maxRate) / 100; 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; } $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'], ); 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 nextLvAttr($heroDb){ // 165 249 327 $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 (in_array($val['attr_id'],array( kHAT_Def, kHAT_Hp, kHAT_Atk ))){ $temp = $val['val'] * ($heroLevelMeta['promote']+1); $val['val'] = sprintf("%.2f",substr(sprintf("%.3f", $temp), 0, -1)); } // if ($val['attr_id'] == kHAT_Def){ // //升级后防御力:上一级防御力*((提升幅度+1)^防御力系数) // $temp = $val['val'] * (pow(($heroLevelMeta['promote']+1),$levelAttrMeta['def_rate'])); //// $temp = $val['val'] * ($heroLevelMeta['promote']+1); // $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; } public static function LvUpAddAttr($heroDb){ $heroMeta = mt\Hero::get($heroDb['hero_id']); $baseAttr = mt\Hero::getHeroAttr($heroMeta); $attrLv1 = emptyReplace(json_decode($heroDb['base_attr'], true), array()); $randAttr = emptyReplace(json_decode($heroDb['rand_attr'], true), array()); $paramQualityMeta = mt\Parameter::getVal('quality',0); $heroLevelMeta = \mt\HeroLevel::getByLevel($heroDb['hero_lv']+1); foreach ($randAttr as &$val){ if (in_array($val['attr_id'],array( kHAT_Def, kHAT_Hp, kHAT_Atk ))){ switch ($val['quality']){ case 1 :{ $paramMeta = mt\Parameter::getVal('d_probability',0); }break; case 2 :{ $paramMeta = mt\Parameter::getVal('c_probability',0); }break; case 3 :{ $paramMeta = mt\Parameter::getVal('b_probability',0); }break; case 4 :{ $paramMeta = mt\Parameter::getVal('a_probability',0); }break; default:{ $paramMeta = null; $temp = $val['val'] * ($heroLevelMeta['promote']+1); $val['val'] = sprintf("%.2f",substr(sprintf("%.3f", $temp), 0, -1)); } } $quality = $val['quality']; if ($paramMeta){ $weightArr = explode("|",$paramMeta); $totalWeight = 0; foreach ($weightArr as $value){ $weights = explode(":",$value); $totalWeight += $weights[1]; } $currWeight = 0; $rnd = rand() % $totalWeight; foreach ($weightArr as $value){ $weights = explode(":",$value); $currWeight += $weights[1]; if ($currWeight > $rnd) { $quality = $weights[0]; break; } } if ($val['quality'] != $quality){ $rate = explode('|',$paramQualityMeta); $minRate = $rate[$quality-1] * 100; $maxRate = $rate[$quality] * 100 - 1; if ($quality == 5){ $maxRate = $rate[$quality] * 100; } $finalRate = rand($minRate,$maxRate) / 100; $tempVal = round(self::_getAttrVal($baseAttr,$val['attr_id']) * $finalRate,2); $val['quality'] = $quality; $v = ($tempVal / self::_getAttrVal($attrLv1,$val['attr_id'])) * $val['val'] * (1 + $heroLevelMeta['promote']); $val['val'] = sprintf("%.2f",substr(sprintf("%.3f", $v), 0, -1)); self::_setAttrVal($attrLv1,$val['attr_id'],array( 'val'=>$tempVal, 'quality'=>$quality, )); }else{ $temp = $val['val'] * ($heroLevelMeta['promote']+1); $val['val'] = sprintf("%.2f",substr(sprintf("%.3f", $temp), 0, -1)); } } } } return array( 'base_attr' => $attrLv1, 'rand_attr' => $randAttr, ); } private static function _getAttrVal($baseAttr,$attrId){ $hashAttr = array(); foreach ($baseAttr as $value){ $hashAttr[$value['attr_id']] =$value; } return $hashAttr[$attrId]['val']; } private static function _setAttrVal(&$baseAttr,$attrId,$attrVal){ foreach ($baseAttr as &$value){ if ($value['attr_id'] == $attrId){ $value['val'] = $attrVal['val']; $value['quality'] = $attrVal['quality']; } } } }