pet.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Administrator
  5. * Date: 2020/2/3
  6. * Time: 21:17
  7. */
  8. class ModelPet{
  9. public function getPetConfig($petId = 0,$versionFlag = false){
  10. $cacheKey = okeys::PetConfig("",$versionFlag);
  11. $arrJson = oo::commonOprRedis('config')->hGetAll($cacheKey);
  12. $arr = funs::getArrFromJsonArr($arrJson);
  13. if(empty($arr)||(!$petId&&empty($arr[$petId]))){
  14. $tb = otable::PetConfig($versionFlag);
  15. $arr = oo::commonOprDb('config')->getAll("SELECT * FROM {$tb}",MYSQLI_ASSOC);
  16. if(!empty($arr)){
  17. foreach ($arr as $k=>$v){
  18. if($versionFlag){
  19. $v['addExp'] = json_decode($v['addExp'],true)??[];
  20. $v['skillBase'] = json_decode($v['skillBase'],true)??[];
  21. $arr[$k] = $v;
  22. $cache[$v['id']] = json_encode($v);
  23. }else{
  24. $cache[$v['id']] = json_encode($arr[$k]);
  25. }
  26. }
  27. $arr = array_column($arr,null,'id');
  28. oo::commonOprRedis('config')->hMset($cacheKey,$cache);
  29. oo::commonOprRedis('config')->expire($cacheKey,oo::redisRandomExpire(7*86400));
  30. }
  31. }
  32. $data = $petId===0?array_values($arr):$arr[$petId];
  33. return $data;
  34. }
  35. public function savePetConfig($data){
  36. $tb = otable::PetConfig(true);
  37. $petId = $data['petId'];
  38. unset($data['petId']);
  39. $update = "";
  40. foreach ($data as $key=>$row){
  41. $update .= "`$key`='$row',";
  42. }
  43. $update = trim($update,",");
  44. oo::commonOprDb('common')->query("UPDATE {$tb} SET {$update} WHERE id={$petId} LIMIT 1 ",false);
  45. oo::commonOprRedis('config')->delete(okeys::PetConfig("",true));
  46. }
  47. public function getPetExpConfig($lv = 0){
  48. $cacheKey = okeys::PetExpConfig();
  49. $arrJson = oo::commonOprRedis('config')->hGetAll($cacheKey);
  50. $arr = funs::getArrFromJsonArr($arrJson);
  51. if(empty($arr)||(!$lv&&empty($arr[$lv]))){
  52. $tb = otable::PetExpConfig();
  53. $arr = oo::commonOprDb('config')->getAll("SELECT * FROM {$tb} WHERE 1",MYSQLI_ASSOC);
  54. if(!empty($arr)){
  55. foreach ($arr as $k=>$v){
  56. $cache[$v['lv']] = json_encode($arr[$k]);
  57. }
  58. $arr = array_column($arr,null,'lv');
  59. oo::commonOprRedis('config')->hMset($cacheKey,$cache);
  60. oo::commonOprRedis('config')->expire($cacheKey,oo::redisRandomExpire(7*86400));
  61. }
  62. }
  63. $data = $lv===0?$arr:$arr[$lv]['exp'];
  64. return $data;
  65. }
  66. public function savePetExpConfig($data){
  67. $tb = otable::PetExpConfig();
  68. foreach ($data as $key=>$row){
  69. oo::commonOprDb('common')->query("UPDATE {$tb} SET `exp`={$row} WHERE lv={$key} LIMIT 1 ",false);
  70. }
  71. oo::commonOprRedis('config')->delete(okeys::PetExpConfig());
  72. }
  73. /**
  74. * 获取宠物等级配置
  75. * @param $petId
  76. * @param $lv
  77. * @return array|mixed
  78. * Created by: Owen
  79. * Created on: 2020/8/25 15:47
  80. */
  81. public function getPetLevelConfig($petId=1,$lv=1){
  82. $cacheKey = okeys::PetLevelConfig($petId);
  83. $cache = oo::commonOprRedis('Config')->hGet($cacheKey,$lv);
  84. if(empty($cache)){
  85. $tb = otable::PetExpConfig2();
  86. $cache = oo::commonOprDb('config')->getOne("SELECT * FROM {$tb} WHERE petId={$petId} AND lv={$lv}",MYSQLI_ASSOC);
  87. if(!empty($cache)){
  88. oo::commonOprRedis('Config')->hSet($cacheKey,$lv,json_encode($cache));
  89. }
  90. }else{
  91. $cache = json_decode($cache,true);
  92. }
  93. return $cache;
  94. }
  95. /**
  96. * 孵化宠物
  97. * @param $uid
  98. * @param $petId
  99. * @return array
  100. * Created by: Owen
  101. * Created on: 2020/8/21 17:51
  102. */
  103. public function incubatePet($uid,$petId){
  104. $pet = self::getUserPet($uid,$petId);
  105. if(empty($pet)){
  106. $petConfig = self::getPetConfig($petId,true);
  107. if(empty($petConfig)){
  108. return ['code'=>-4,"msg"=>"宠物不存在"];
  109. }
  110. if($petConfig['incubateType'] == 0){
  111. $userAssetsInfo = oo::commonOprModel('member')->getUserAssetsInfo($uid);
  112. if($userAssetsInfo['levelId'] < $petConfig['incubateFrom']){
  113. return ['code'=>-3,"msg"=>'等级不足解锁'];
  114. }
  115. }else if($petConfig['incubateType'] == 2){
  116. if(!oo::commonOprModel('card')->isGetAllCardByGroup($uid,$petConfig['incubateFrom'])){
  117. return ['code'=>-3,"msg"=>'解锁条件不足'];
  118. }
  119. }
  120. $tb = otable::UserPet($uid);
  121. $time = time();
  122. oo::commonOprDb('common')->query("INSERT INTO {$tb} (uid,petId,nick,getTime,star) VALUES ('{$uid}','{$petId}','pet','{$time}',-1)", false);
  123. $userPet = oo::commonOprDb('common')->getOne("SELECT * FROM {$tb} WHERE uid={$uid} AND petId={$petId} LIMIT 1", MYSQLI_ASSOC);
  124. oo::commonOprRedis('User')->hSet(okeys::UserPet2($uid),$petId,json_encode($userPet));
  125. oo::commonOprModel('ta')->setEventData($uid,"pet_unlock",["pet_unlock_id"=>$petId,]);
  126. return ['code'=>1,'data'=>self::getUserPet($uid,$petId)];
  127. }else{
  128. return ['code'=>-2,"msg"=>"宠物已激活"];
  129. }
  130. }
  131. /**
  132. * 激活宠物
  133. * @param $uid
  134. * @param $petId
  135. * @return string
  136. * Created by: Owen
  137. * Created on: 2020/8/21 17:50
  138. */
  139. public function activatePet($uid,$petId){
  140. $petList = self::getUserPet($uid,0,true);
  141. foreach ($petList as $row){
  142. if($row['petId'] == $petId && $row['selected'] == 0){
  143. self::updateUserPetInfo($uid,$row['petId'],['selected'=>1]);
  144. }else if($row['petId'] != $petId && $row['selected'] == 1){
  145. self::updateUserPetInfo($uid,$row['petId'],['selected'=>0]);
  146. }
  147. }
  148. oo::commonOprRedis('usercache')->setex(okeys::CurUserPet($uid),$petId,oo::redisRandomExpire(7*24*60*60));
  149. return oo::response(1,self::getUserPet($uid,$petId),"",true);
  150. }
  151. /**
  152. * 获取宠物信息
  153. * @param $uid
  154. * @param int $petId
  155. * @param bool $orig
  156. * @return array|mixed
  157. * Created by: Owen
  158. * Created on: 2020/8/21 17:50
  159. */
  160. public function getUserPet($uid,$petId = 0,$orig = false){
  161. $cacheKey = okeys::UserPet2($uid);
  162. $userPetArr = oo::commonOprRedis('User')->hGetAll($cacheKey);
  163. if(empty($userPetArr)){
  164. $tb = otable::UserPet($uid);
  165. $userPetArr = oo::commonOprDb('common')->getAll("SELECT * FROM {$tb} WHERE uid={$uid}", MYSQLI_ASSOC);
  166. if(!empty($userPetArr)){
  167. foreach ($userPetArr as $row){
  168. oo::commonOprRedis('User')->hSet($cacheKey,$row['petId'],json_encode($row));
  169. $row['star'] == -1 && self::checkUserPetStar($uid,$row['petId'],$row['lv']);
  170. }
  171. oo::commonOprRedis('User')->expire($cacheKey,oo::redisRandomExpire(7*24*60*60));
  172. }
  173. }else{
  174. $userPetArr = array_values($userPetArr);
  175. foreach ($userPetArr as $key=>$row){
  176. $userPetArr[$key] = json_decode($row,true);
  177. }
  178. }
  179. foreach ($userPetArr as $key=>$row){
  180. !$orig && $userPetArr[$key] = array_merge($userPetArr[$key],self::getPetDetail($row['petId']??1,$row['lv']??1));
  181. if($row['selected'] == 1){
  182. oo::commonOprRedis('usercache')->setex(okeys::CurUserPet($uid),$row['petId'],oo::redisRandomExpire(7*24*60*60));
  183. }
  184. if($petId&&$petId==$row['petId']){
  185. $petId2 = $userPetArr[$key];
  186. }
  187. }
  188. if($petId2){
  189. $userPetArr = $petId2;
  190. }else if($petId){
  191. $userPetArr = [];
  192. }
  193. return $userPetArr;
  194. }
  195. /**
  196. * 更新用户宠物信息
  197. * @param $uid
  198. * @param $petId
  199. * @param $updateInfo
  200. * @return bool
  201. * Created by: Owen
  202. * Created on: 2020/8/24 19:50
  203. */
  204. public function updateUserPetInfo($uid,$petId,$updateInfo){
  205. if(empty($updateInfo)){
  206. return false;
  207. }
  208. $userPet = self::getUserPet($uid,$petId,true);
  209. if(empty($userPet)){
  210. return false;
  211. }
  212. foreach ($updateInfo as $key=>$row){
  213. $userPet[$key] = $row;
  214. }
  215. return self::setUserPetInfo($uid,$petId,$userPet);
  216. }
  217. /**
  218. * 原子加用户宠物数据
  219. * @param $uid
  220. * @param $petId
  221. * @param $updateInfo
  222. * @return bool
  223. * Created by: Owen
  224. * Created on: 2020/8/24 19:50
  225. */
  226. public function addUserPetInfo($uid,$petId,$updateInfo){
  227. if(empty($updateInfo)){
  228. return false;
  229. }
  230. $userPet = self::getUserPet($uid,$petId,true);
  231. if(empty($userPet)){
  232. return false;
  233. }
  234. foreach ($updateInfo as $key=>$row){
  235. $userPet[$key] += $row;
  236. }
  237. return self::setUserPetInfo($uid,$petId,$userPet);
  238. }
  239. /**
  240. * 更新入队
  241. * @param $uid
  242. * @param $petId
  243. * @param $info
  244. * @return bool
  245. * Created by: Owen
  246. * Created on: 2020/8/24 19:58
  247. */
  248. public function setUserPetInfo($uid,$petId,$info){
  249. $cacheKey = okeys::UserPet2($uid);
  250. $info['isLanding'] = 1;
  251. $bool = oo::commonOprRedis('User')->hSet($cacheKey,$petId,json_encode($info));
  252. oo::commonOprRedis('common')->expire($cacheKey,oo::redisRandomExpire(7*24*60*60));
  253. /** 数据落地标识 */
  254. oo::commonOprRedis('common')->zAdd(okeys::Landing("PET", $uid),time(),$uid);
  255. return $bool;
  256. }
  257. /**
  258. * 获取宠物经验增益详情数据
  259. * @param $petId
  260. * @param $lv
  261. * @return mixed
  262. * Created by: Owen
  263. * Created on: 2020/8/24 18:30
  264. */
  265. public function getPetDetail($petId,$lv){
  266. $lv = max($lv,1);
  267. $config = self::getPetLevelConfig($petId,$lv);
  268. $userPet['nextLvExp'] = intval($config['exp']);
  269. $userPet['gainNum'] = self::getPetGain($petId,$lv);
  270. $userPet['nextGainNum'] = self::getPetGain($petId,$lv + 1);
  271. $userPet['nextStar'] = $config['star'];
  272. return $userPet;
  273. }
  274. /**
  275. * 当前激活宠物
  276. * @param $uid
  277. * @return false|int
  278. * Created by: Owen
  279. * Created on: 2020/8/21 17:50
  280. */
  281. public function getCurUserPet($uid){
  282. $cache = oo::commonOprRedis('usercache')->get(okeys::CurUserPet($uid));
  283. if($cache){
  284. return $cache;
  285. }
  286. return 1;
  287. }
  288. /**
  289. * 追加宠物经验
  290. * @param $uid
  291. * @param $petId
  292. * @param $exp
  293. * Created by: Owen
  294. * Created on: 2020/8/21 17:49
  295. */
  296. public function addUserPetExp($uid,$petId,$exp,$from = 0){
  297. self::addUserPetInfo($uid,$petId,['exp'=>$exp]) && self::upLevelUserPet($uid,$petId,$exp,$from);
  298. }
  299. /**
  300. * 宠物升级
  301. * @param $uid
  302. * @param $petId
  303. * @return bool
  304. * Created by: Owen
  305. * Created on: 2020/8/24 20:00
  306. */
  307. public function upLevelUserPet($uid,$petId,$exp = 0,$from = 0){
  308. $userPet = self::getUserPet($uid,$petId);
  309. if($userPet['nextLvExp']<=$userPet['exp'] && $userPet['nextLvExp'] != -1 && !empty($userPet['nextLvExp'])){
  310. $needAddStar= 0;
  311. $updateInfo = ['exp'=> - $userPet['nextLvExp'],'lv'=>1];
  312. $updateInfo['star'] = 0;
  313. $userPet['star'] == -1 && self::checkUserPetStar($uid,$petId,$userPet['lv']); // 检测宠物星星补发
  314. $config = self::getPetLevelConfig($petId,$userPet['lv']);
  315. $needAddStar += intval($config['star']);
  316. $updateInfo['star'] += intval($config['star']);
  317. $bool = self::addUserPetInfo($uid,$petId,$updateInfo);
  318. $bool && $needAddStar && oo::commonOprModel('member')->optProperty($uid,['star'=>$needAddStar],'+',112,"宠物升级:".$userPet['lv']) && self::upLevelUserPet($uid,$petId,$exp,$from);
  319. oo::commonOprModel('ta')->setEventData($uid,"pet_up",[
  320. "pet_up_id"=>$petId,
  321. "pet_up_addexptype"=>$from,
  322. "pet_up_addexp"=>$exp,
  323. "pet_up_oldlevel"=>$userPet['lv'],
  324. "pet_up_newlevel"=>$userPet['lv'] + 1,
  325. ]);
  326. $key = [1=>'pet_steal_level',3=>'pet_attack_level',2=>'pet_shield_level'][$petId];
  327. oo::commonOprModel('ta')->setEventData($uid,'user_set',[$key=>$userPet['lv'] + 1]);
  328. return $bool;
  329. }
  330. return false;
  331. }
  332. /**
  333. * 检测宠物星星
  334. * @param $uid
  335. * @param $petId
  336. * @param $lv
  337. * Created by: Owen
  338. * Created on: 2020/8/25 18:49
  339. */
  340. public function checkUserPetStar($uid,$petId,$lv){
  341. if($lv == 1){
  342. self::addUserPetInfo($uid,$petId,['star'=>0]);
  343. }else{
  344. $needAddStar = 0;
  345. $levelId = [];
  346. for($i=1;$i<$lv;$i++){
  347. $config = self::getPetLevelConfig($petId,$i);
  348. $needAddStar += intval($config['star']);
  349. $levelId[] = $i;
  350. }
  351. self::addUserPetInfo($uid,$petId,['star'=>$needAddStar + 1]) && oo::commonOprModel('member')->optProperty($uid,['star'=>$needAddStar],'+',112,"宠物等级星星补发:".implode(',',$levelId));
  352. }
  353. }
  354. /**
  355. * 喂食宠物(免费粮食)
  356. * @param $uid
  357. * @param $petId
  358. * @param $refreshTime
  359. * @return string
  360. * Created by: Owen
  361. * Created on: 2020/8/21 17:49
  362. */
  363. public function freeFeedPet($uid,$petId,$refreshTime = 0){
  364. $cacheKey = okeys::FreeFeedPet($uid);
  365. if($refreshTime){
  366. $time = time();
  367. $data['freeFeedStatus'] = $time + 24*60*60;
  368. oo::commonOprRedis('common')->setex($cacheKey,1,24*60*60);
  369. return oo::response(1,$data,"刷新成功");
  370. }
  371. if(oo::commonOprRedis('common')->get($cacheKey)){
  372. return oo::response(-2,[],"已喂食");
  373. }
  374. $time = time();
  375. $userPet = self::getUserPet($uid,$petId);
  376. if(empty($userPet)){
  377. return oo::response(-3,[],"宠物未激活");
  378. }
  379. if($userPet['feedEffecteTime']<$time){
  380. $feedEffecteTime = $time + 15*60;
  381. }else{
  382. $feedEffecteTime = $userPet['feedEffecteTime'] + 15*60;
  383. }
  384. $userPet['lastFeedTime'] = $time;
  385. $userPet['feedEffecteTime'] = $feedEffecteTime;
  386. self::updateUserPetInfo($uid,$petId,['lastFeedTime'=>$time,'feedEffecteTime'=>$feedEffecteTime]);
  387. oo::commonOprRedis('common')->setex($cacheKey,1,24*60*60);
  388. //免费喂食标记
  389. oo::commonOprRedis('statistics')->setex(okeys::participationPetKey($uid, $petId), 0, oo::todayDeadline());
  390. $data['petData'] = $userPet;
  391. $data['freeFeedStatus'] = $time + 24*60*60;
  392. oo::commonOprModel('ta')->setEventData($uid,"pet_feed",[
  393. "pet_feed_id"=>$petId,
  394. "pet_feed_type"=>1,
  395. "pet_feed_remain_time"=>max($feedEffecteTime - time(),0),
  396. ]);
  397. return oo::response(1,$data,"喂食成功",true);
  398. }
  399. /**
  400. * 喂食宠物
  401. * @param $uid
  402. * @param $petId
  403. * @param $addTime
  404. * @return bool
  405. * Created by: Owen
  406. * Created on: 2020/8/24 20:03
  407. */
  408. public function feedPet($uid,$petId,$addTime = 0,$from = 0){
  409. if($addTime){
  410. $activateTime = $addTime;
  411. }else{
  412. $petConfig = self::getPetConfig($petId,true);
  413. self::addUserPetExpBy($uid,$petId,"feedAddExp");
  414. $activateTime = $petConfig['activateTime'];
  415. }
  416. $time = time();
  417. $userPet = self::getUserPet($uid,$petId);
  418. if($userPet['feedEffecteTime']<$time){
  419. $feedEffecteTime = $time + $activateTime;
  420. }else{
  421. $feedEffecteTime = $userPet['feedEffecteTime'] + $activateTime;
  422. }
  423. //付费喂食标记
  424. oo::commonOprRedis('statistics')->setex(okeys::participationPetKey($uid, $petId), 1, oo::todayDeadline());
  425. oo::commonOprModel('ta')->setEventData($uid,"pet_feed",[
  426. "pet_feed_id"=>$petId,
  427. "pet_feed_type"=>$from,
  428. "pet_feed_remain_time"=>max($feedEffecteTime - time(),0),
  429. ]);
  430. return self::updateUserPetInfo($uid,$petId,['lastFeedTime'=>$time,'feedEffecteTime'=>$feedEffecteTime]);
  431. }
  432. /**
  433. * 使用宠物技能
  434. * @param $uid
  435. * @param $petId 1偷宠物 2盾牌宠物 3打宠物
  436. * @param int $num
  437. * @return bool|float|int|array
  438. * @throws Exception
  439. * Created by: Owen
  440. * Created on: 2020/8/21 17:49
  441. */
  442. public function usePetSkill($uid,$petId,$num = 0){
  443. if($petId != self::getCurUserPet($uid)){
  444. return false;
  445. }
  446. $userPet = self::getUserPet($uid,$petId);
  447. if(!empty($userPet) && $userPet['feedEffecteTime']>time()){
  448. $gainNum = self::getPetGain($petId, $userPet['lv']);
  449. if ($petId == 1) {
  450. $gainNum = $gainNum * 0.01;
  451. $num = abs(intval($num * $gainNum));
  452. return [$num,$gainNum];
  453. }else if ($petId == 2){
  454. if(IS_DEBUF){
  455. return true;
  456. }
  457. if(oo::commonOprRedis('common')->setnx(okeys::PetSkillToday($uid),1)){
  458. oo::commonOprRedis('common')->expire(okeys::PetSkillToday($uid),oo::todayDeadline());
  459. return true;
  460. }
  461. if(random_int(0,100)<$gainNum){
  462. return true;
  463. }
  464. }else if($petId == 3){
  465. return $num * $gainNum * 0.01;
  466. }
  467. }
  468. return false;
  469. }
  470. /**
  471. * 获取宠物收益值
  472. * @param $petId
  473. * @param $lv
  474. * @return float|int
  475. * Created by: Owen
  476. * Created on: 2020/8/21 17:48
  477. */
  478. public function getPetGain($petId,$lv){
  479. $config = self::getPetLevelConfig($petId,$lv);
  480. return intval($config['skill']);
  481. }
  482. /**
  483. * 追加宠物经验
  484. * @param $uid
  485. * @param $petId
  486. * @param $from
  487. * @return bool
  488. * Created by: Owen
  489. * Created on: 2020/9/17 19:15
  490. */
  491. public function addUserPetExpBy($uid,$petId,$from,$bet=1,$rid=122,$reason=''){
  492. if($from != "feedAddExp" && self::getCurUserPet($uid) != $petId){
  493. return false;
  494. }
  495. $config = self::getPetConfig($petId,true);
  496. $expConfig = $config['addExp'];
  497. $userPetLv = self::getUserPet($uid,$petId)['lv'];
  498. $expReward = [];
  499. foreach ($expConfig as $exp){
  500. if($userPetLv <= $exp['minLv']){
  501. $expReward = $exp;
  502. break;
  503. }
  504. }
  505. if(empty($expReward[$from])){
  506. return false;
  507. }
  508. $count = intval($expReward[$from]*$bet);
  509. self::addUserPetExp($uid,$petId,$count,intval(["feedAddExp"=>1,"attackAddExp"=>2,"defenseAddExp"=>2,"stealAddExp"=>2][$from]));
  510. oo::commonOprModel('currency')->log($uid,8,"+",$count,0,$rid,$reason."基数{$expReward[$from]},bet:{$bet}");
  511. return $expReward[$from];
  512. }
  513. }