123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- <?php
- namespace loyalsoft;
- /**
- * 抽奖 模块
- * @version
- * 1.0.1 英雄抽奖, 奖品限定为英雄, 2017.07.20 by --gwang
- * 1.0.0 从active模块拆分出来, Created at 2017-7-20. by --gwang
- * @author gwang (mail@wanggangzero.cn)
- * @copyright ? 2017-7-20, SJZ LoyalSoft Corporation & gwang. All rights reserved.
- */
- class Lotterys {
- /**
- * 改造方案:
- * 1. 抽奖添加卡槽参数, 告诉服务端结果放到哪个卡槽中.
- * 2. 抽奖时验证卡槽是否为空, 不空不可继续.
- * 3. 抽奖结果不直接发放到玩家身上, 而是放到卡槽中, 等待读条完毕, 手动领取.
- * 4. 增加领取抽奖结果api, 验证冷却完毕, 提取到玩家身上.
- */
- /**
- * [6511] 抽奖 - 领取保底奖励, 奖品直接发放到玩家身上, 不计冷却时间
- * @param Req $req
- */
- static function baodiLottery($req) {
- # 保底奖励领取方案: 不需要扣除花费, 只需清零抽奖次数.
- $user = $req->userInfo->game;
- $lottery = new UserLotteryModel($req->userInfo->game->privateState->lottery);
- if (count($req->paras) < 1) { # 提取参数
- return Resp::err(ErrCode::parasnotenough_msg);
- }
- $lot_type = $req->paras[0]; # 抽奖类型: 金币,钻石,友情点... (物品id)
- $cishu = 10; # 想要领取的奖励id(1,2,3)等阶对应需要满足的抽奖次数
- if (count($req->paras) > 1) { # 如果没有传第二个参数, 默认给1阶奖励(10次),
- $cishu = $req->paras[1];
- }
- if ($lottery->baodiLotterys->$lot_type < $cishu) { # 检查累计次数
- return Resp::err(ErrCode::lottery_baodi_times_lt);
- }
- $baodi = GameConfig::choujiang_baodi_getItem($lot_type, $cishu); # 保底奖池
- if (null == $baodi) { # 找不到
- return Resp::err(ErrCode::err_const_no);
- }
- $settings = GameConfig::choujiang_settings_getItem($lot_type); # 设定
- if (null == $settings) { # 找不到
- return Resp::err(ErrCode::err_const_no);
- }
- # 当达到, 最后一次的时候, 执行减法扣除对应的值?或者其他算法.
- # 保底的奖励物品, 要切换, 换成不同抽奖道具, 对应不同的奖品池, 因为道具价值不一样.
- if ($lottery->baodiDrawed->$lot_type >= $cishu) {
- return Resp::err(ErrCode::active_hasgetted);
- }
- $lottery->baodiDrawed->$lot_type = $cishu;
- if ($cishu == $settings->baodiMax) {
- $lottery->baodiDrawed->$lot_type = 0; # 防刷, 已经领过的次数要加记录
- $lottery->baodiLotterys->$lot_type -= $cishu; # 清零次数
- }
- $err = self::Dice($baodi, 1, $rewardstr); # 投骰子
- if ($err) {
- return Resp::err($err);
- }
- if (strlen($rewardstr) <= 0) { # 抽奖结果为空
- return Resp::err(ErrCode::err_innerfault);
- }
- $err = StoreProc::AddMultiItemInStore($req, $rewardstr, 3); # 发放物品
- if ($err) {
- return Resp::err($cishu);
- }
- $req->userInfo->game->privateState->lottery = $lottery;
- UserProc::updateUserInfo($req); # 回存数据
- // var_dump($lottery);
- return Resp::ok(array('err' => 0, # # 返回值
- 'store' => $user->store,
- 'heros' => $user->heros,
- 'reward' => $rewardstr,
- 'baodi' => $lottery->baodiLotterys,
- 'baodidrawed' => $lottery->baodiDrawed
- ));
- }
- /**
- * [6510] 活动 - 抽奖 - 新手引导定制版
- * @param Req $req
- */
- static function demoLottery($req) {
- $user = $req->userInfo->game;
- if (count($req->paras) < 1) { # 参数数量不足
- return Resp::err(ErrCode::parasnotenough_msg);
- }
- # # 提取参数
- $type = $req->paras[0]; # 金币,钻石,友情点...
- $number = 1; # 抽奖次数
- if (count($req->paras) > 1) { # 可选参数
- $number = $req->paras[1];
- }
- # 记录抽奖次数
- $err = self::AddLotteryTimes($user->privateState->lottery, $type, $left_cishu, $number);
- if ($err) {
- return Resp::err($err);
- }
- $err = self::ConsumeLotteryCost($user, $type, $number);
- if ($err) {
- return Resp::err($err);
- }
- $req->userInfo->game = $user; // 回写
- $err = self::Dice(JsonUtil::decode(glc()->choujiang_guide_items), $number, $rewardstr);
- if ($err) { // 出错了
- return Resp::err($err);
- }
- if (strlen($rewardstr) <= 0) {
- return Resp::err(ErrCode::err_innerfault);
- }
- $err = StoreProc::AddMultiItemInStore($req, $rewardstr, 3); # 发放物品
- if ($err) {
- return Resp::err($err);
- }
- UserProc::updateUserInfo($req); # 回存数据
- return Resp::ok(array('err' => 0, # 返回值
- 'store' => $user->store,
- 'heros' => $user->heros,
- 'reward' => $rewardstr,
- 'baodi' => $user->privateState->lottery->baodiLotterys,
- 'left_cishu' => $left_cishu));
- }
- //
- // <editor-fold defaultstate="collapsed" desc=" 抽奖 - 经典版">
- /**
- * [6509] 活动 - 抽奖
- * @param Req $req
- * @ deprecated since version 1.0.1 新版只出英雄, . . .
- * Ps. 1.0.0版可支持产出道具
- */
- static function Lottery($req) {
- $user = $req->userInfo->game;
- if (count($req->paras) < 1) { # 提取参数
- return Resp::err(ErrCode::parasnotenough_msg);
- }
- $type = $req->paras[0]; # 金币,钻石,友情点... (物品id)
- $number = 1; # 抽奖次数
- if (count($req->paras) > 1) { # 可选参数
- $number = $req->paras[1];
- }
- # 记录抽奖次数
- $err = self::AddLotteryTimes($user->privateState->lottery, $type, $left_cishu, $number);
- if ($err) {
- return Resp::err($err);
- }
- # 扣除抽奖花费
- $err = self::ConsumeLotteryCost($user, $type, $number);
- if ($err) {
- return Resp::err($err);
- }
- # 回写user数据
- $req->userInfo->game = $user;
- # 对奖池依解锁等级进行过滤
- $arr = self::FilterPrizepool($req, GameConfig::choujiang_getItem($type));
- $err = self::Dice($arr, $number, $rewardstr); # 投骰子
- if ($err) { # 出错了
- return Resp::err($err);
- }
- if (strlen($rewardstr) <= 0) { # 抽奖结果为空
- return Resp::err(ErrCode::err_innerfault);
- }
- $err = StoreProc::AddMultiItemInStore($req, $rewardstr, 3); # 发放物品
- if ($err) { # 出错了
- return Resp::err($err);
- }
- UserProc::updateUserInfo($req); # 回存数据
- return Resp::ok(array('err' => 0, # # 返回值
- 'store' => $user->store,
- 'heros' => $user->heros,
- 'reward' => $rewardstr,
- 'baodi' => $user->privateState->lottery->baodiLotterys,
- 'left_cishu' => $left_cishu));
- }
- // </editor-fold>
- //
- // <editor-fold defaultstate="collapsed" desc=" 抽奖 - 新生到校版">
- /**
- * [6513] 活动 - 抽奖 查询信息(卡槽)
- * @param Req $req
- */
- static function Lottery_Info($req) {
- return Resp::ok(array(
- 'lottery' => new UserLotteryModel($req->userInfo->game->privateState->lottery)
- ));
- }
- /**
- * [6515] 活动 - 抽奖 缩短搜索时间
- * @param Req $req
- */
- static function Lottery_speedup_search($req) {
- if (count($req->paras) < 1) { # 提取参数
- return Resp::err(ErrCode::parasnotenough_msg);
- }
- $id = $req->paras[0]; # 卡槽id: 0,1,2,
- $slotid = 'slot' . $id;
- $lottery = new UserLotteryModel($req->userInfo->game->privateState->lottery);
- $slot = new LotterySlotModel($lottery->$slotid);
- if ($slot->locked) { # 卡槽尚未解锁
- return Resp::err(ErrCode::err_lottery_slot_locked);
- }
- if (!$slot->herotype) { # 卡槽空
- return Resp::err(ErrCode::err_lottery_slot_emputy);
- }
- $itemid = glc()->choujiang_dachequan_itemid; # 打车券的itemid
- if ($slot->opents > now()) { # 已经到时间了,无需扣除,
- # 先不替客户省钱了, 只要客户端发送请求就执行.
- $err = StoreProc::removeItemFromStore($req->userInfo->game->store, $itemid, 1);
- if ($err) {
- return Resp::err($err);
- }
- $slot->opents = now(-15); # 往前偏移15秒
- }
- $lottery->$slotid = $slot;
- $req->userInfo->game->privateState->lottery = $lottery;
- UserProc::updateUserInfo($req); # 回写数据
- return Resp::ok(array('slot' => $slot)); # 返回
- }
- /**
- * [6514] 活动 - 抽奖 解锁卡槽
- * @param Req $req
- */
- static function Lottery_unlock_Slot($req) {
- if (count($req->paras) < 1) { # 提取参数
- return Resp::err(ErrCode::parasnotenough_msg);
- }
- $id = $req->paras[0]; # 卡槽id: 0,1,2,
- $slotid = 'slot' . $id;
- $lottery = new UserLotteryModel($req->userInfo->game->privateState->lottery);
- $slot = new LotterySlotModel($lottery->$slotid);
- if (!$slot->locked) { # 卡槽已经解锁
- return Resp::err(ErrCode::err_lottery_slot_unlocked);
- }
- # 判断等级, 等级不足则扣除钻石
- $sm_slot = GameConfig::choujiang_slot_getItem($id); # slot 配置
- if ($req->userInfo->game->level < $sm_slot->level) { # 等级不足时需要扣除钻石
- if (!UserGameModel::Consume_Cash($req->userInfo->game, $sm_slot->cash)) {
- return Resp::err(ErrCode::notenough_cash_msg);
- }
- }
- $slot->locked = false; # 解锁卡槽
- $lottery->$slotid = $slot;
- $req->userInfo->game->privateState->lottery = $lottery;
- UserProc::updateUserInfo($req); # 回写数据
- return Resp::ok(array('slot' => $slot)); # 返回
- }
- /**
- * [6512] 活动 - 抽奖 领取到校英雄
- * @param Req $req
- */
- static function drawReachHero($req) {
- if (count($req->paras) < 1) { # 提取参数
- return Resp::err(ErrCode::parasnotenough_msg);
- }
- $slotid = 'slot' . $req->paras[0]; # 卡槽id: 0,1,2,
- $lottery = new UserLotteryModel($req->userInfo->game->privateState->lottery);
- $slot = new LotterySlotModel($lottery->$slotid);
- if ($slot->locked) { # 卡槽尚未解锁
- return Resp::err(ErrCode::err_lottery_slot_locked);
- }
- if ($slot->opents > now()) { # 卡槽时间未到
- return Resp::err(ErrCode::err_lottery_slot_time);
- }
- if (!$slot->herotype || !$slot->herostar) { # 卡槽数据异常
- return Resp::err(ErrCode::err_lottery_slot_emputy);
- }
- # 提取英雄...
- $he = HeroProc::AddHeroWithStar($req, $slot->herotype, $slot->herostar);
- $slot->Clear();
- $lottery->$slotid = $slot;
- $req->userInfo->game->privateState->lottery = $lottery; # 数据回写
- UserProc::updateUserInfo($req);
- return Resp::ok(array(
- 'heros' => $req->userInfo->game->heros,
- 'hero' => $he,
- 'slot' => $slot
- ));
- }
- /**
- * [6509] 活动 - 抽奖
- * @param Req $req
- */
- static function Lottery_Hero($req) {
- if (count($req->paras) < 1) { # 提取参数
- return Resp::err(ErrCode::parasnotenough_msg);
- }
- $type = $req->paras[0]; # 金币,钻石,友情点... (物品id)
- $slotid = 'slot' . $req->paras[1]; # 卡槽id: 0,1,2,3
- #
- // 检查卡槽是否空闲
- $user = $req->userInfo->game;
- $lottery = new UserLotteryModel($user->privateState->lottery);
- $slot = new LotterySlotModel($lottery->$slotid);
- if ($slot->locked) { # 卡槽尚未解锁
- return Resp::err(ErrCode::err_lottery_slot_locked);
- }
- if ($slot->opents > now() || $slot->herotype) { # 卡槽使用中
- return Resp::err(ErrCode::err_lottery_slot_not_emputy);
- }
- $number = 1; # 抽奖次数, 固定为1
- $err = self::AddLotteryTimes($lottery, $type, $left_cishu, $number); # 记录抽奖次数
- if ($err) {
- return Resp::err($err);
- }
- $err = self::ConsumeLotteryCost($user, $type, $number); # 扣除抽奖花费(通知书)
- if ($err) {
- return Resp::err($err);
- }
- $err = self::Dice(GameConfig::choujiang_getItem($type), # 投骰子
- $number, $rewardstr);
- if ($err) {
- return Resp::err($err);
- }
- if (strlen($rewardstr) <= 0) { # 抽奖结果为空
- return Resp::err(ErrCode::err_innerfault);
- }
- # 依据抽奖次数找到星级数据库
- $xingji = self::FindStarSource($lottery->todayLotterys->$type);
- if (!$xingji) {
- return Resp::err(ErrCode::err_const_no, "抽奖-星级");
- }
- self::DiceOutStar($xingji, $star); # 计算星级
- $val = explode(",", $rewardstr);
- $itemId = $val[0];
- # 发放英雄(异化为英雄放入卡槽...
- // $he = HeroProc::AddHeroWithStar($req, $itemId, $star);
- $slot->herostar = $star;
- $slot->herotype = $itemId;
- $slot->opents = now() + self::DiceOutCoolingTiem(GameConfig::choujiang_searchtime_getItem($star));
- $lottery->$slotid = $slot;
- $user->privateState->lottery = $lottery; # 回写数据
- $req->userInfo->game = $user; # 回写user数据
- UserProc::updateUserInfo($req); # 回存数据
- return Resp::ok(array('err' => 0, # # 返回值
- 'store' => $user->store,
- 'slot' => $slot, # # 卡槽信息
- 'left_cishu' => $left_cishu));
- }
- // </editor-fold>
- //
- // <editor-fold defaultstate="collapsed" desc=" -==- 辅助函数 -==- ">
- /**
- * 增加抽奖次数
- * @param LotterySlotModel $user
- * @param type $type
- * @param int $left_cishu out
- * @param type $number
- * @return int errno
- */
- static function AddLotteryTimes(&$lottery, $type, &$left_cishu, $number = 1) {
- $todaylotterys = $lottery->todayLotterys;
- $totalLottreys = $lottery->totalLotterys;
- $baodiLotterys = $lottery->baodiLotterys;
- if (!$todaylotterys) {
- $todaylotterys = JsonUtil::decode(sprintf('{"%s":0}', $type));
- }
- if (!$totalLottreys) {
- $totalLottreys = JsonUtil::decode(sprintf('{"%s":0}', $type));
- }
- if (!$baodiLotterys) {
- $baodiLotterys = JsonUtil::decode(sprintf('{"%s":0}', $type));
- }
- if (!isset($todaylotterys->$type)) {
- $todaylotterys->$type = 0;
- }
- if (!isset($totalLottreys->$type)) {
- $totalLottreys->$type = 0;
- }
- if (!isset($baodiLotterys->$type)) {
- $baodiLotterys->$type = 0;
- }
- $todaylotterys->$type += $number;
- $totalLottreys->$type += $number;
- $baodiLotterys->$type += $number;
- $settings = GameConfig::choujiang_settings_getItem($type);
- if (null == $settings) {
- return ErrCode::err_const_no;
- }
- $limit = $settings->dailyLimit;
- if ($limit > 0 && $todaylotterys->$type > $limit) {
- return ErrCode::err_lottery_daily_limit; # 达到每次次数限制, (@广电总局)
- }
- $left_cishu = $limit - $todaylotterys->$type;
- if ($left_cishu < 0) {
- $left_cishu = 0;
- }
- $lottery->todayLotterys = $todaylotterys;
- $lottery->totalLotterys = $totalLottreys;
- $lottery->baodiLotterys = $baodiLotterys;
- return ErrCode::ok;
- }
- /**
- * 扣除抽奖花费
- * @param UserGameModel $user
- * @param type $type
- * @param type $number
- * @return int errno
- */
- static function ConsumeLotteryCost($user, $type, $number = 1) {
- $settings = GameConfig::choujiang_settings_getItem($type);
- if (null == $settings) {
- return ErrCode::err_const_no;
- }
- $amt = $settings->price;
- if ($number > 1) { # n连抽
- $amt *= $number;
- }
- switch ($type) { // 扣除花费
- case META_GOLD_ITEMID: # 金币抽奖
- if (!UserGameModel::Consume_Gold($user, $amt)) {
- return ErrCode::notenough_gold_msg;
- }
- break;
- case META_CASH_ITEMID: # 钻石抽奖
- if (!UserGameModel::Consume_Cash($user, $amt)) {
- return ErrCode::notenough_cash_msg; # 钻石余额不足
- }
- break;
- case META_FriendShipPoit_ItemId: # 友情点
- if (!UserGameModel::Consume_FriendShipPoint($user, $amt)) {
- return ErrCode::notenough_friendshippoint;
- }
- break;
- default: # 从包裹中消耗道具
- $err = StoreProc::removeItemFromStore($user->store, $type, $amt);
- if ($err) {
- return $err;
- }
- break;
- }
- return ErrCode::ok;
- }
- /**
- * 过滤奖池
- * @param Req $req
- * @param array $arr 奖池
- */
- static function FilterPrizepool($req, $arr) {
- # 等级限制
- $ret = array_filter($arr, function ($value) use($req) {
- return($req->userInfo->game->level >= $value->unlock_level);
- });
- return $ret;
- }
- /**
- * 投骰子
- * @param assoc_array $arr 抽奖物品概率
- * @param int $number 连抽次数
- * @return string itemid,num;itemid,num;...
- */
- static function Dice($arr, $number, &$rewardstr) {
- $max = 0; # 计算物品权重总和
- array_walk($arr, function ($value) use(&$max) {
- $max += $value->probability;
- });
- if (!$max) { # 配置数据有问题
- return ErrCode::err_const_no;
- }
- $reward = ArrayInit();
- for ($i = 0; $i < $number; $i++) {
- $rnd = CommUtil::random(1, $max); # 投骰子
- $start = 0;
- $rew = null;
- foreach ($arr as $item) { # 循环判断落入那个物品上
- if ($start < $rnd && $rnd <= $start + $item->probability) { # 落入区间
- $rew = $item; # 记录物品
- break;
- }
- $start += $item->probability; # 继续判断是否落入下一物品的区间
- } # foreach end
- if (!$rew) {
- return ErrCode::lottery_noselecteditem;
- }
- $reward[] = implode(',', array($rew->rewardItemId, $rew->number));
- } # for end
- $rewardstr = implode(';', $reward);
- return ErrCode::ok;
- }
- /**
- * 找到计算星级的数据源
- * @param type $cishu
- * @return array of sm_choujiang_xingji
- */
- public static function FindStarSource($cishu) {
- foreach (GameConfig::choujiang_xingji() as $ci => $arr) {
- if ($cishu <= $ci) { # 找到对应的阶段了
- return $arr;
- }
- }
- return JsonUtil::decode('[{"star":1,"probability":100}]'); # 默认值, 爽吧
- }
- /**
- * @deprecated since version now
- * 投骰子获得一个卡牌的星级
- * @param type $arr
- * @param type $ret
- * @return type
- */
- public static function DiceOutStar($arr, &$ret) {
- $max = 0;
- array_walk($arr, function ($value) use(&$max) {
- $max += $value->probability; # 计算物品权重总和
- });
- if (!$max) { # 配置数据有问题
- return ErrCode::err_const_no;
- }
- $rnd = CommUtil::random(1, $max); # 投骰子
- $start = 0; # 起点
- foreach ($arr as $item) { # 循环判断落入那个物品上
- if ($start < $rnd && $rnd <= $start + $item->probability) { # 落入区间
- $ret = $item->star; # 设置结果
- return ErrCode::ok;
- }
- $start += $item->probability; # 继续判断是否落入下一物品的区间
- } # foreach end
- return ErrCode::lottery_noselecteditem; # 没有找到对应的结果
- }
- /**
- * 依据星级投骰子获得一个到校时间
- * @param type $arr
- * @return type
- */
- public static function DiceOutCoolingTiem($arr) {
- $max = 0;
- array_walk($arr, function ($value) use(&$max) {
- $max += $value->probability; # 计算物品权重总和
- });
- $rnd = CommUtil::random(1, $max); # 投骰子
- $start = 0; # 起点
- foreach ($arr as $item) { # 循环判断落入那个物品上
- if ($start < $rnd && $rnd <= $start + $item->probability) { # 落入区间
- return $item->time; # 设置结果, 返回值
- }
- $start += $item->probability; # 继续判断是否落入下一物品的区间
- } # foreach end
- return 780; # 没有找到对应的结果, 给一个默认值13分钟
- }
- /**
- * 清理每天的抽奖次数记录
- * @param Req $req
- */
- public static function ClearLotteryRecord($req) {
- $req->userInfo->game->privateState->lottery->todayLotterys = ObjectInit();
- }
- // </editor-fold>
- //
- }
|