특기 획득 구조 변경
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
class SpecialityHelper{
|
||||
//const GENERIC = 0x0;
|
||||
const DISABLED = 0x1;
|
||||
|
||||
const STAT_LEADERSHIP = 0x2;
|
||||
const STAT_STRENGTH = 0x4;
|
||||
const STAT_INTEL = 0x8;
|
||||
|
||||
const ARMY_FOOTMAN = 0x100;
|
||||
const ARMY_ARCHER = 0x200;
|
||||
const ARMY_CAVALRY = 0x400;
|
||||
const ARMY_WIZARD = 0x800;
|
||||
const ARMY_SIEGE = 0x1000;
|
||||
|
||||
const REQ_DEXTERITY = 0x4000;
|
||||
|
||||
const WEIGHT_NORM = 1;
|
||||
const WEIGHT_PERCENT = 2;
|
||||
|
||||
static $domesticInv = null;
|
||||
static $warInv = null;
|
||||
|
||||
private function __construct(){
|
||||
}
|
||||
|
||||
public static function getDomesticClassByName(?string $type):string{
|
||||
if($type === null || $type === ''){
|
||||
$type = GameConst::$defaultSpecialDomestic;
|
||||
}
|
||||
|
||||
if(static::$domesticInv){
|
||||
if(!key_exists($type, static::$domesticInv)){
|
||||
throw new \InvalidArgumentException('올바르지 않은 특기명:',$type);
|
||||
}
|
||||
return static::$domesticInv[$type];
|
||||
}
|
||||
|
||||
$cache = [];
|
||||
foreach(static::getSpecialDomesticList(false) as $className=>$classObj){
|
||||
$cache[$classObj->getName()] = $className;
|
||||
}
|
||||
static::$domesticInv = $cache;
|
||||
return $cache[$type];
|
||||
}
|
||||
|
||||
public static function getWarClassByName(?string $type):string{
|
||||
if($type === null || $type === ''){
|
||||
$type = GameConst::$defaultSpecialWar;
|
||||
}
|
||||
|
||||
if(static::$warInv){
|
||||
if(!key_exists($type, static::$warInv)){
|
||||
throw new \InvalidArgumentException('올바르지 않은 특기명:',$type);
|
||||
}
|
||||
return static::$warInv[$type];
|
||||
}
|
||||
|
||||
$cache = [];
|
||||
foreach(static::getSpecialWarList(false) as $className=>$classObj){
|
||||
$cache[$classObj->getName()] = $className;
|
||||
}
|
||||
static::$warInv = $cache;
|
||||
return $cache[$type];
|
||||
}
|
||||
|
||||
private static function calcCondGeneric(array $general) : int {
|
||||
$myCond = 0;
|
||||
|
||||
$leadership = $general['leadership']??50;
|
||||
$strength = $general['strength']??50;
|
||||
$intel = $general['intel']??50;
|
||||
|
||||
if ($leadership * 0.95 > $strength && $leadership * 0.95 > $intel) {
|
||||
$myCond |= self::STAT_LEADERSHIP;
|
||||
}
|
||||
else if($strength >= $intel){
|
||||
$myCond |= self::STAT_STRENGTH;
|
||||
}
|
||||
else {
|
||||
$myCond |= self::STAT_INTEL;
|
||||
}
|
||||
|
||||
return $myCond;
|
||||
}
|
||||
|
||||
private static function calcCondDexterity(array $general) : int {
|
||||
$dex = [
|
||||
static::ARMY_FOOTMAN => $general['dex1']??0,
|
||||
static::ARMY_ARCHER => $general['dex2']??0,
|
||||
static::ARMY_CAVALRY => $general['dex3']??0,
|
||||
static::ARMY_WIZARD => $general['dex4']??0,
|
||||
static::ARMY_SIEGE => $general['dex5']??0,
|
||||
];
|
||||
|
||||
$dexSum = array_sum($dex);
|
||||
$dexBase = Util::round(sqrt($dexSum) / 4);
|
||||
|
||||
if(Util::randBool(0.8)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(mt_rand(0, 99) < $dexBase){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!$dexSum){
|
||||
return array_rand($dex);
|
||||
}
|
||||
|
||||
return array_keys($dex, max($dex))[0];
|
||||
}
|
||||
|
||||
/** @return BaseSpecial[] */
|
||||
public static function getSpecialDomesticList(bool $onlyAvailable=true):array{
|
||||
$result = [];
|
||||
if(!$onlyAvailable){
|
||||
$specialObj = buildGeneralSpecialDomesticClass(GameConst::$defaultSpecialDomestic);
|
||||
$result[GameConst::$defaultSpecialDomestic] = $specialObj;
|
||||
}
|
||||
|
||||
foreach(GameConst::$availableSpecialDomestic as $specialID){
|
||||
$specialObj = buildGeneralSpecialDomesticClass($specialID);
|
||||
$result[$specialID] = $specialObj;
|
||||
}
|
||||
|
||||
if(!$onlyAvailable){
|
||||
foreach(GameConst::$availableSpecialDomestic as $specialID){
|
||||
$specialObj = buildGeneralSpecialDomesticClass($specialID);
|
||||
$result[$specialID] = $specialObj;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @return BaseSpecial[] */
|
||||
public static function getSpecialWarList(bool $onlyAvailable=true):array{
|
||||
$result = [];
|
||||
if(!$onlyAvailable){
|
||||
$specialObj = buildGeneralSpecialDomesticClass(GameConst::$defaultSpecialDomestic);
|
||||
$result[GameConst::$defaultSpecialDomestic] = $specialObj;
|
||||
}
|
||||
|
||||
foreach(GameConst::$availableSpecialDomestic as $specialID){
|
||||
$specialObj = buildGeneralSpecialDomesticClass($specialID);
|
||||
$result[$specialID] = $specialObj;
|
||||
}
|
||||
|
||||
if(!$onlyAvailable){
|
||||
foreach(GameConst::$availableSpecialDomestic as $specialID){
|
||||
$specialObj = buildGeneralSpecialDomesticClass($specialID);
|
||||
$result[$specialID] = $specialObj;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function pickSpecialDomestic(array $general) : string{
|
||||
$pAbs = [];
|
||||
$pRel = [];
|
||||
|
||||
$myCond = static::calcCondGeneric($general);
|
||||
|
||||
foreach(static::getSpecialDomesticList() as $specialID=>$specialObj){
|
||||
$conds = $specialObj::$type;
|
||||
$name = $specialObj->getName();
|
||||
$weightType = $specialObj::$selectWeightType;
|
||||
$weight = $specialObj::$selectWeight;
|
||||
|
||||
$valid = false;
|
||||
foreach($conds as $cond){
|
||||
if($cond === ($cond & $myCond)){
|
||||
$valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$valid){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if($weightType === static::WEIGHT_PERCENT){
|
||||
$pAbs[$specialID] = $weight;
|
||||
}
|
||||
else{
|
||||
$pRel[$specialID] = $weight;
|
||||
}
|
||||
}
|
||||
|
||||
if($pAbs){
|
||||
if($pRel){
|
||||
$pAbs[0] = max(0, 100 - array_sum($pAbs));
|
||||
}
|
||||
$id = Util::choiceRandomUsingWeight($pAbs);
|
||||
if($id){
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
|
||||
$id = Util::choiceRandomUsingWeight($pRel);
|
||||
if($id){
|
||||
return $id;
|
||||
}
|
||||
|
||||
throw new MustNotBeReachedException();
|
||||
}
|
||||
|
||||
public static function pickSpecialWar(array $general) : string{
|
||||
$reqDex = [];
|
||||
$pAbs = [];
|
||||
$pRel = [];
|
||||
|
||||
$myCond = static::calcCondGeneric($general);
|
||||
$myCond |= static::calcCondDexterity($general);
|
||||
|
||||
foreach(static::getSpecialWarList() as $specialID=>$specialObj){
|
||||
$conds = $specialObj::$type;
|
||||
$name = $specialObj->getName();
|
||||
$weightType = $specialObj::$selectWeightType;
|
||||
$weight = $specialObj::$selectWeight;
|
||||
|
||||
$valid = false;
|
||||
foreach($conds as $cond){
|
||||
if($cond === ($cond & $myCond)){
|
||||
$valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$valid){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if($cond & self::REQ_DEXTERITY){
|
||||
$reqDex[$specialID] = $weight;
|
||||
}
|
||||
else if($weightType === static::WEIGHT_PERCENT){
|
||||
$pAbs[$specialID] = $weight;
|
||||
}
|
||||
else{
|
||||
$pRel[$specialID] = $weight;
|
||||
}
|
||||
}
|
||||
|
||||
if($reqDex){
|
||||
return Util::choiceRandomUsingWeight($reqDex);
|
||||
}
|
||||
|
||||
if($pAbs){
|
||||
if($pRel){
|
||||
$pAbs[0] = max(0, 100 - array_sum($pAbs));
|
||||
}
|
||||
$id = Util::choiceRandomUsingWeight($pAbs);
|
||||
if($id){
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
|
||||
$id = Util::choiceRandomUsingWeight($pRel);
|
||||
if($id){
|
||||
return $id;
|
||||
}
|
||||
|
||||
throw new MustNotBeReachedException();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user