Compare commits

...
75 Commits
Author SHA1 Message Date
Hide_D 3f0cd2ad64 fix: illuminate 2021-09-21 03:13:07 +09:00
Hide_D 41420d1954 Illuminate: ready. (critical)
- DB에서 illuminate를 가져올 수 있도록 설정
- 업그레이듵 불가, RootDB, DB를 직접 수정해야함
2021-09-21 03:06:42 +09:00
Hide_D 6e5a72b170 fix: 자동 사령턴 조정이 되지 않는 버그 2021-09-19 15:44:49 +09:00
Hide_D 4b19e6aec8 fix: 명예의 전당 검색 2021-09-19 13:38:40 +09:00
Hide_D 58572cbc36 scenario: 쿠키런 킹덤 임시 구현 2021-09-19 03:03:05 +09:00
Hide_D 096d5766bf conf: vue-style-loader에 esbuild-loader적용 2021-09-18 04:53:26 +09:00
Hide_D f5c5b56492 dep: babel-loader + ts-loader => esbuild-loader 2021-09-18 04:31:31 +09:00
Hide_D 69c69d63e6 dep: package upgrade 2021-09-18 03:52:27 +09:00
Hide_D 3fd8b21867 misc: lint warning, 불필요 파일 정리 2021-09-18 03:49:04 +09:00
Hide_D 8660e8cd85 fix: NPC포상 설정 메시지 수정 2021-09-18 03:42:20 +09:00
Hide_D 8458f725f2 fix: 사망 시 유산 포인트 관련 환불/초기화가 없는 문제 2021-09-18 03:36:08 +09:00
Hide_D 366678c965 fix: 장수 생성창 보이기/숨기기, 턴 시간 고정 표기 수정 2021-09-18 02:49:47 +09:00
Hide_D 336b5668db fix & inheritAction: 랜덤 유니크 습득시 환불 가능하게 수정 2021-09-18 00:15:00 +09:00
Hide_D 55886269ea inheritAction: 설문조사에서는 특정 유니크 구입 기능 해제 2021-09-18 00:06:20 +09:00
Hide_D 0b3698595b fix: hash -> gitHash 2021-09-17 23:40:47 +09:00
Hide_D 05e43a39db fix: 턴 초기화, 전특 초기화 표기 방식 변경 2021-09-17 23:37:53 +09:00
Hide_D 5737ad3db2 fix: 턴 초기화, 특기 초기화 포인트 안내가 1스텝 늦음 2021-09-17 23:34:33 +09:00
Hide_D 4ac174eb9a fix: 반계시도에는 구분 코드가 동작하지 않았음 2021-09-17 23:17:13 +09:00
Hide_D 895eec10b4 fix: 비급 반계가 전특 반계와 같이 동작하지 않는 버그 수정 2021-09-17 23:07:45 +09:00
Hide_D e0d891e89a fix: 재야일 때에는 임관 년도 증가하지 않도록 2021-09-17 03:14:14 +09:00
Hide_D adf7734b85 fix: 생성하자마자 임관 1년차로 나오는 문제 수정 2021-09-17 03:12:38 +09:00
Hide_D 5362be9c21 inheritPoint: 로그 기록 2021-09-17 02:39:11 +09:00
Hide_D 847ece52f2 fix: summernote.css 2021-09-16 22:39:19 +09:00
Hide_D 851c59d22c fix: 유저전투장 긴급포상 쌀 2021-09-16 22:37:31 +09:00
Hide_D 0669534bba fix: 궁 유니크 저격 계수 2021-09-16 22:24:29 +09:00
Hide_D 05db47e62a fix: 설문조사에서 환불 불가능한 문제 수정 2021-09-16 22:06:57 +09:00
Hide_D 4a0e608d1c fix: itemTrials 삭제 후 통째로 array가 비면 array도 마저 삭제 2021-09-16 22:00:35 +09:00
Hide_D 45fe73af86 fix: eventColumn에 aux 추가 2021-09-16 21:47:32 +09:00
Hide_D 4d9fcd657f fix: vote에서 aux 2021-09-16 21:43:37 +09:00
Hide_D a057deb0fe fix: 유니크를 얻는 턴이 아니더라도 환불은 하도록 수정 2021-09-16 21:38:43 +09:00
Hide_D 4766210a7d 랜임 실패시 실행 턴. 요양 -> 인탐 2021-09-16 21:24:52 +09:00
Hide_D fd26aae6d3 schema 변경 2021-09-16 04:13:34 +09:00
Hide_DandGitea c5c092cc8e Join: 양식 일부 수정 2021-09-15 19:06:15 +00:00
Hide_DandGitea 58c0a21d90 fix: 턴 시간 변경 코드 2021-09-15 19:06:15 +00:00
Hide_DandGitea 8dc567f966 fix: LazyVarUpdate unset 2021-09-15 19:06:15 +00:00
Hide_DandGitea 942b2752f5 fix: previous inheritPoint 지정값 버그 2021-09-15 19:06:15 +00:00
Hide_DandGitea b9259353f4 misc: layout 2021-09-15 19:06:15 +00:00
Hide_DandGitea 86c614dd40 inheritAction: UI 1차 완성 2021-09-15 19:06:15 +00:00
Hide_DandGitea 1a010a16a9 miisc: 간격 조절 2021-09-15 19:06:15 +00:00
Hide_DandGitea d5b5726b1e InheritAction: UI 턴 초기화, 전투 특기 초기화, 랜덤 유니크
- 턴 초기화에 버그가 있는듯?
2021-09-15 19:06:15 +00:00
Hide_DandGitea d06f3b6bdf inheritStore: 버프/디버프 구매 UI 2021-09-15 19:06:15 +00:00
Hide_DandGitea 97a28f716c inheritAction: 특정 전특 획득 2021-09-15 19:06:15 +00:00
Hide_DandGitea f54bdfcea0 Inherit: Action 완료? 2021-09-15 19:06:15 +00:00
Hide_DandGitea 5958c4b0ba InheritAction: 유니크 입찰, 랜덤 아이템 2021-09-15 19:06:15 +00:00
Hide_DandGitea 7c3db881c7 dep: bootstrap-vue-3 추가
- 아직 없는 기능이 많으므로 단순 출력은 CoreUI Vue 동시 활용
- 불편..
2021-09-15 19:06:15 +00:00
Hide_DandGitea 51ee2e1b2c misc: License 2021-09-15 19:06:15 +00:00
Hide_DandGitea baa813004b fix: 메인페이지 지도를 반응형으로 2021-09-15 19:06:15 +00:00
Hide_DandGitea 86b5269d3d inheritPoint: 가입폼
- 기본 동작
- 턴시간에는 버그 있음
2021-09-15 19:06:15 +00:00
Hide_DandGitea 860e6dacac vue: join 생성 완료 메시지 2021-09-15 19:06:15 +00:00
Hide_DandGitea 22025bd89e vue: join 2021-09-15 19:06:15 +00:00
Hide_DandGitea ed9301455d fix: inheritSkill 연산을 위해 aux 필요 2021-09-15 19:06:15 +00:00
Hide_DandGitea 35df84e059 fix: maxPhase 연산에서는 oppose가 없음 2021-09-15 19:06:15 +00:00
Hide_DandGitea 62deebf310 fix: inheritUnique 처리 수정 2021-09-15 19:06:15 +00:00
Hide_DandGitea 7ed4bd5c01 build: join 페이지 준비 2021-09-15 19:06:15 +00:00
Hide_DandGitea c8eb9332b4 misc: 오타 수정 2021-09-15 19:06:15 +00:00
Hide_DandGitea 1df55f9168 api: gateway, ingame 모두 가능하도록 변경 2021-09-15 19:06:15 +00:00
Hide_DandGitea b726c6aa96 유산 포인트로 랜덤 유니크 획득 2021-09-15 19:06:15 +00:00
Hide_DandGitea 0a71962652 balance: 아이템 습득 확률 조정
- 아이템을 소유할 수록, 획득 확률이 기존보다 훨씬 더 낮아진다.
2021-09-15 19:06:15 +00:00
Hide_DandGitea 160946ef74 feat: 아이템 유산포인트로 입찰한 경우 최종적으로 얻는 기능 추가 2021-09-15 19:06:15 +00:00
Hide_DandGitea 1dc67317dc balance: 유니크 아이템을 얻을 수 있는 커맨드 증가
- 강행, 거병, 견문, 군량매매, 귀환, 등용, 물자조달, 이동, 장비매매, 증여, 헌납
2021-09-15 19:06:15 +00:00
Hide_DandGitea 08f4a2e8bf feat: TriggerInheritBuff 구현 2021-09-15 19:06:15 +00:00
Hide_DandGitea 11ffdaa8f7 feat: '계략약화' 특성을 onCalcOpposeStat으로 이동 2021-09-15 19:06:15 +00:00
Hide_DandGitea 0f853303a4 feat: 전투 상대방의 특정 수치를 접근할 수 있는 callback류 생성 2021-09-15 19:06:15 +00:00
Hide_DandGitea d225eb9b16 inheritBuff 준비 2021-09-15 19:06:15 +00:00
Hide_D d926e4b8bc api: 규격 정의 2021-09-12 04:59:34 +09:00
Hide_D 3e2df1d4d8 api: join 2021-09-12 03:22:11 +09:00
Hide_D d670dbf081 feat: 장수 생성 시 유산 포인트에 따라 생성해주는 기능 추가 2021-09-12 02:59:49 +09:00
Hide_D f510a312e3 fix: 은퇴용 유산 포인트 코드가 항상 적용되는 문제 수정 2021-09-12 02:07:29 +09:00
Hide_D 19c44e3d31 fix: 수뇌가 소재 도시에 도시 관련 사령턴(백동 등) 실행시 발생하는 버그 수정
- 백동 + 성수 등등
2021-09-11 19:35:30 +09:00
Hide_D d0848aee67 fix: 가오픈 정보 안나오는 버그 수정 2021-09-10 22:49:30 +09:00
Hide_D f4b4b6811c fix: bootstrap4 package order 문제
- vue3 + bootstrap5 적용 전까진 고통 받아야...
- 당분간 Popper, jQuery가 제대로 export 되었는지 확인 필요
2021-09-10 22:26:14 +09:00
Hide_D fecb3f1f7b fix: gateway tooltip 2021-09-10 21:38:32 +09:00
Hide_D 4c924c0763 fix: 내 정보 로그 추가 불러오기 안되는 문제 수정 2021-09-10 21:05:26 +09:00
Hide_D f1e8d70554 fix: browser support 범위 추가 2021-09-10 18:43:29 +09:00
Hide_D 7d11bc152e fix: 오타 수정 2021-09-09 01:27:29 +09:00
1826 changed files with 151892 additions and 1933 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License
Copyright (c) 2020 Hide_D, 62che
Copyright (c) 2021 Hide_D, 62che
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace sammo;
require(__DIR__ . '/vendor/autoload.php');
if (!class_exists('\\sammo\\RootDB')) {
Json::dieWithReason('No DB');
}
APIHelper::launch(dirname(__FILE__));
+3 -1
View File
@@ -28,7 +28,9 @@
"catfan/medoo": "^1.5",
"phan/phan": "*",
"erusev/parsedown-extra": "^0.8.1",
"nette/caching": "^3.0"
"nette/caching": "^3.0",
"illuminate/database": "^8.61",
"illuminate/events": "^8.61"
},
"autoload": {
"psr-4": {
Generated
+980 -2
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2aeb036fc53a6fdc343bd2707d4697ee",
"content-hash": "317938cff7b30806f4e385a70f4943fc",
"packages": [
{
"name": "brandonwamboldt/utilphp",
@@ -265,6 +265,101 @@
],
"time": "2021-07-31T17:03:58+00:00"
},
{
"name": "doctrine/inflector",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/9cf661f4eb38f7c881cac67c75ea9b00bf97b210",
"reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^7.0",
"phpstan/phpstan": "^0.11",
"phpstan/phpstan-phpunit": "^0.11",
"phpstan/phpstan-strict-rules": "^0.11",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Inflector\\": "lib/Doctrine/Inflector"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
"keywords": [
"inflection",
"inflector",
"lowercase",
"manipulation",
"php",
"plural",
"singular",
"strings",
"uppercase",
"words"
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.0.x"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
"type": "tidelift"
}
],
"time": "2020-05-29T15:13:26+00:00"
},
{
"name": "erusev/parsedown",
"version": "1.7.4",
@@ -707,6 +802,497 @@
},
"time": "2021-04-26T09:17:50+00:00"
},
{
"name": "illuminate/bus",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/bus.git",
"reference": "808097c0dfd893309bd77b00139586c516b965c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/bus/zipball/808097c0dfd893309bd77b00139586c516b965c9",
"reference": "808097c0dfd893309bd77b00139586c516b965c9",
"shasum": ""
},
"require": {
"illuminate/collections": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/pipeline": "^8.0",
"illuminate/support": "^8.0",
"php": "^7.3|^8.0"
},
"suggest": {
"illuminate/queue": "Required to use closures when chaining jobs (^7.0)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Bus\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Bus package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-08-10T16:49:48+00:00"
},
{
"name": "illuminate/collections",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/collections.git",
"reference": "18fa841df912ec56849351dd6ca8928e8a98b69d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/collections/zipball/18fa841df912ec56849351dd6ca8928e8a98b69d",
"reference": "18fa841df912ec56849351dd6ca8928e8a98b69d",
"shasum": ""
},
"require": {
"illuminate/contracts": "^8.0",
"illuminate/macroable": "^8.0",
"php": "^7.3|^8.0"
},
"suggest": {
"symfony/var-dumper": "Required to use the dump method (^5.1.4)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Support\\": ""
},
"files": [
"helpers.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Collections package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-08T12:48:16+00:00"
},
{
"name": "illuminate/container",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/container.git",
"reference": "862b64ea4ab56e307a1676104a1b93295d347ad0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/container/zipball/862b64ea4ab56e307a1676104a1b93295d347ad0",
"reference": "862b64ea4ab56e307a1676104a1b93295d347ad0",
"shasum": ""
},
"require": {
"illuminate/contracts": "^8.0",
"php": "^7.3|^8.0",
"psr/container": "^1.0"
},
"provide": {
"psr/container-implementation": "1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Container\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Container package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-09T13:55:23+00:00"
},
{
"name": "illuminate/contracts",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
"reference": "ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913",
"reference": "ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0",
"psr/container": "^1.0",
"psr/simple-cache": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Contracts\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Contracts package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-08T12:09:40+00:00"
},
{
"name": "illuminate/database",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/database.git",
"reference": "acc11d6839ddb3b694bc6585177fa5141b70c693"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/database/zipball/acc11d6839ddb3b694bc6585177fa5141b70c693",
"reference": "acc11d6839ddb3b694bc6585177fa5141b70c693",
"shasum": ""
},
"require": {
"ext-json": "*",
"illuminate/collections": "^8.0",
"illuminate/container": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/macroable": "^8.0",
"illuminate/support": "^8.0",
"php": "^7.3|^8.0",
"symfony/console": "^5.1.4"
},
"suggest": {
"doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6|^3.0).",
"fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
"illuminate/console": "Required to use the database commands (^8.0).",
"illuminate/events": "Required to use the observers with Eloquent (^8.0).",
"illuminate/filesystem": "Required to use the migrations (^8.0).",
"illuminate/pagination": "Required to paginate the result set (^8.0).",
"symfony/finder": "Required to use Eloquent model factories (^5.1.4)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Database\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Database package.",
"homepage": "https://laravel.com",
"keywords": [
"database",
"laravel",
"orm",
"sql"
],
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-13T18:43:43+00:00"
},
{
"name": "illuminate/events",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/events.git",
"reference": "7def78033f29cd0c0383513b27c291d233a7f90e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/events/zipball/7def78033f29cd0c0383513b27c291d233a7f90e",
"reference": "7def78033f29cd0c0383513b27c291d233a7f90e",
"shasum": ""
},
"require": {
"illuminate/bus": "^8.0",
"illuminate/collections": "^8.0",
"illuminate/container": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/macroable": "^8.0",
"illuminate/support": "^8.0",
"php": "^7.3|^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Events\\": ""
},
"files": [
"functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Events package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-08-16T21:45:47+00:00"
},
{
"name": "illuminate/macroable",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/macroable.git",
"reference": "300aa13c086f25116b5f3cde3ca54ff5c822fb05"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/macroable/zipball/300aa13c086f25116b5f3cde3ca54ff5c822fb05",
"reference": "300aa13c086f25116b5f3cde3ca54ff5c822fb05",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Support\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Macroable package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2020-10-27T15:20:30+00:00"
},
{
"name": "illuminate/pipeline",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/pipeline.git",
"reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/pipeline/zipball/23aeff5b26ae4aee3f370835c76bd0f4e93f71d2",
"reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2",
"shasum": ""
},
"require": {
"illuminate/contracts": "^8.0",
"illuminate/support": "^8.0",
"php": "^7.3|^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Pipeline\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Pipeline package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-03-26T18:39:16+00:00"
},
{
"name": "illuminate/support",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
"reference": "b0a21c41163381dd9a5abbd68fe85ed7b4247d30"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/support/zipball/b0a21c41163381dd9a5abbd68fe85ed7b4247d30",
"reference": "b0a21c41163381dd9a5abbd68fe85ed7b4247d30",
"shasum": ""
},
"require": {
"doctrine/inflector": "^1.4|^2.0",
"ext-json": "*",
"ext-mbstring": "*",
"illuminate/collections": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/macroable": "^8.0",
"nesbot/carbon": "^2.31",
"php": "^7.3|^8.0",
"voku/portable-ascii": "^1.4.8"
},
"conflict": {
"tightenco/collect": "<5.5.33"
},
"suggest": {
"illuminate/filesystem": "Required to use the composer class (^8.0).",
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^1.3|^2.0).",
"ramsey/uuid": "Required to use Str::uuid() (^4.0).",
"symfony/process": "Required to use the composer class (^5.1.4).",
"symfony/var-dumper": "Required to use the dd function (^5.1.4).",
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.2)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Support\\": ""
},
"files": [
"helpers.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Support package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-13T18:43:43+00:00"
},
{
"name": "league/plates",
"version": "v3.4.0",
@@ -902,6 +1488,100 @@
],
"time": "2021-05-28T08:32:12+00:00"
},
{
"name": "nesbot/carbon",
"version": "2.53.1",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
"reference": "f4655858a784988f880c1b8c7feabbf02dfdf045"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f4655858a784988f880c1b8c7feabbf02dfdf045",
"reference": "f4655858a784988f880c1b8c7feabbf02dfdf045",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.1.8 || ^8.0",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php80": "^1.16",
"symfony/translation": "^3.4 || ^4.0 || ^5.0"
},
"require-dev": {
"doctrine/orm": "^2.7",
"friendsofphp/php-cs-fixer": "^3.0",
"kylekatarnls/multi-tester": "^2.0",
"phpmd/phpmd": "^2.9",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12.54",
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
"squizlabs/php_codesniffer": "^3.4"
},
"bin": [
"bin/carbon"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-3.x": "3.x-dev",
"dev-master": "2.x-dev"
},
"laravel": {
"providers": [
"Carbon\\Laravel\\ServiceProvider"
]
},
"phpstan": {
"includes": [
"extension.neon"
]
}
},
"autoload": {
"psr-4": {
"Carbon\\": "src/Carbon/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Brian Nesbitt",
"email": "brian@nesbot.com",
"homepage": "https://markido.com"
},
{
"name": "kylekatarnls",
"homepage": "https://github.com/kylekatarnls"
}
],
"description": "An API extension for DateTime that supports 281 different languages.",
"homepage": "https://carbon.nesbot.com",
"keywords": [
"date",
"datetime",
"time"
],
"support": {
"issues": "https://github.com/briannesbitt/Carbon/issues",
"source": "https://github.com/briannesbitt/Carbon"
},
"funding": [
{
"url": "https://opencollective.com/Carbon",
"type": "open_collective"
},
{
"url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
"type": "tidelift"
}
],
"time": "2021-09-06T09:29:23+00:00"
},
{
"name": "netresearch/jsonmapper",
"version": "v4.0.0",
@@ -1684,6 +2364,57 @@
},
"time": "2021-05-03T11:20:27+00:00"
},
{
"name": "psr/simple-cache",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"support": {
"source": "https://github.com/php-fig/simple-cache/tree/master"
},
"time": "2017-10-23T01:57:42+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
@@ -2970,6 +3701,179 @@
],
"time": "2021-06-27T11:44:38+00:00"
},
{
"name": "symfony/translation",
"version": "v5.3.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6",
"reference": "4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "^1.16",
"symfony/translation-contracts": "^2.3"
},
"conflict": {
"symfony/config": "<4.4",
"symfony/dependency-injection": "<5.0",
"symfony/http-kernel": "<5.0",
"symfony/twig-bundle": "<5.0",
"symfony/yaml": "<4.4"
},
"provide": {
"symfony/translation-implementation": "2.3"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^4.4|^5.0",
"symfony/console": "^4.4|^5.0",
"symfony/dependency-injection": "^5.0",
"symfony/finder": "^4.4|^5.0",
"symfony/http-kernel": "^5.0",
"symfony/intl": "^4.4|^5.0",
"symfony/polyfill-intl-icu": "^1.21",
"symfony/service-contracts": "^1.1.2|^2",
"symfony/yaml": "^4.4|^5.0"
},
"suggest": {
"psr/log-implementation": "To use logging capability in translator",
"symfony/config": "",
"symfony/yaml": ""
},
"type": "library",
"autoload": {
"files": [
"Resources/functions.php"
],
"psr-4": {
"Symfony\\Component\\Translation\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v5.3.7"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-08-26T08:22:53+00:00"
},
{
"name": "symfony/translation-contracts",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation-contracts.git",
"reference": "95c812666f3e91db75385749fe219c5e494c7f95"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95",
"reference": "95c812666f3e91db75385749fe219c5e494c7f95",
"shasum": ""
},
"require": {
"php": ">=7.2.5"
},
"suggest": {
"symfony/translation-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Translation\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to translation",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"support": {
"source": "https://github.com/symfony/translation-contracts/tree/v2.4.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-03-23T23:28:01+00:00"
},
{
"name": "tysonandre/var_representation_polyfill",
"version": "0.0.2",
@@ -3080,6 +3984,80 @@
],
"time": "2021-07-08T16:18:03+00:00"
},
{
"name": "voku/portable-ascii",
"version": "1.5.6",
"source": {
"type": "git",
"url": "https://github.com/voku/portable-ascii.git",
"reference": "80953678b19901e5165c56752d087fc11526017c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/voku/portable-ascii/zipball/80953678b19901e5165c56752d087fc11526017c",
"reference": "80953678b19901e5165c56752d087fc11526017c",
"shasum": ""
},
"require": {
"php": ">=7.0.0"
},
"require-dev": {
"phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
},
"suggest": {
"ext-intl": "Use Intl for transliterator_transliterate() support"
},
"type": "library",
"autoload": {
"psr-4": {
"voku\\": "src/voku/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Lars Moelleken",
"homepage": "http://www.moelleken.org/"
}
],
"description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
"homepage": "https://github.com/voku/portable-ascii",
"keywords": [
"ascii",
"clean",
"php"
],
"support": {
"issues": "https://github.com/voku/portable-ascii/issues",
"source": "https://github.com/voku/portable-ascii/tree/1.5.6"
},
"funding": [
{
"url": "https://www.paypal.me/moelleken",
"type": "custom"
},
{
"url": "https://github.com/voku",
"type": "github"
},
{
"url": "https://opencollective.com/portable-ascii",
"type": "open_collective"
},
{
"url": "https://www.patreon.com/voku",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
"type": "tidelift"
}
],
"time": "2020-11-12T00:07:28+00:00"
},
{
"name": "webmozart/assert",
"version": "1.10.0",
@@ -3203,7 +4181,7 @@
"platform": [],
"platform-dev": [],
"platform-overrides": {
"php": "7.3"
"php": "7.4"
},
"plugin-api-version": "2.0.0"
}
+70 -3
View File
@@ -127,8 +127,75 @@ input::-webkit-input-placeholder {
border-radius: .2rem;
}
#running_map{
overflow: hidden;
#running_map {
border: none;
width:700px;
width: 700px;
}
#map-subframe {
display: none;
width: 700px;
}
@media only screen and (min-width : 360px) {
#map-subframe {
display: block;
transform: scale(calc(330 / 700));
transform-origin: 350px 0px;
margin-bottom: -400px;
}
}
@media only screen and (min-width : 440px) {
#map-subframe {
transform: scale(calc(410 / 700));
margin-bottom: -300px;
}
}
@media only screen and (min-width : 480px) {
#map-subframe {
transform: scale(calc(450 / 700));
margin-bottom: -250px;
}
}
@media only screen and (min-width : 520px) {
#map-subframe {
transform: scale(calc(490 / 700));
margin-bottom: -200px;
}
}
@media only screen and (min-width : 576px) {
#map-subframe {
transform: scale(calc(546 / 700));
margin-bottom: -150px;
}
}
@media only screen and (min-width : 640px) {
#map-subframe {
transform: scale(calc(600/700));
margin-bottom: -100px;
}
}
@media only screen and (min-width : 700px) {
#map-subframe {
transform: scale(calc(670 / 700));
margin-bottom: -20px;
}
}
@media only screen and (min-width : 730px) {
#map-subframe {
transform: none;
margin-bottom: 0;
}
}
+30
View File
@@ -2,6 +2,11 @@
namespace sammo;
//https://hub.packtpub.com/eloquent-without-laravel/
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
class RootDB
{
private static $uDB = null;
@@ -12,6 +17,8 @@ class RootDB
private static $dbName = '_tK_dbName_';
private static $port = _tK_port_;
private static $encoding = 'utf8mb4';
private static $collation = 'utf8mb4_general_ci';
private static $globalSalt = '_tK_globalSalt_';
@@ -19,6 +26,29 @@ class RootDB
{
}
public static function illuminate(): Capsule
{
if(self::$uIlluminate !== null){
return self::$uIlluminate;
}
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => self::$host,
'database' => self::$dbName,
'username' => self::$user,
'password' => self::$password,
'charset' => self::$encoding,
'collation' => self::$collation,
], 'root');
$capsule->setEventDispatcher(new Dispatcher(new Container));
$capsule->bootEloquent();
self::$uIlluminate = $capsule;
return $capsule;
}
/**
* DB 객체 생성
*
+1 -1
View File
@@ -28,7 +28,7 @@ $scenarioList = (function(){
if($scenarioIdx !== null && key_exists($scenarioIdx, $scenarioList)){
if($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx]??[])){
$searchScenarioName = $scenarioList[$seasonIdx][$scenarioIdx]['name'];
$searchFilter = $db->sqleval('season = %i AND scenario = %i', $seasonIdx, $scenarioIdx);
}
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
APIHelper::launch(dirname(__FILE__));
+1
View File
@@ -64,6 +64,7 @@ var storedData = <?=Json::encode([
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/dipcenter.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../e_lib/summernote/summernote-bs4.css')?>
<?=WebUtil::printCSS('dist_css/vendors.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
+1 -1
View File
@@ -24,7 +24,7 @@ $admin = $gameStor->getValues(['develcost', 'cost', 'vote_title', 'vote', 'votec
$generalID = Session::getGeneralID();
$general = General::createGeneralObjFromDB($generalID, ['vote','horse','weapon','book','item','npc'], 2);
$general = General::createGeneralObjFromDB($generalID, ['vote','horse','weapon','book','item','npc','imgsvr','picture','aux'], 2);
if($btn == "투표" && $general->getVar('vote') == 0 && $sel > 0) {
$develcost = $admin['develcost'] * 5;
+42 -7
View File
@@ -1,8 +1,16 @@
<?php
namespace sammo;
class DB{
//https://hub.packtpub.com/eloquent-without-laravel/
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
class DB
{
private static $uDB = null;
private static ?Capsule $uIlluminate = null;
private static $host = '_tK_host_';
private static $user = '_tK_user_';
@@ -10,11 +18,36 @@ class DB{
private static $dbName = '_tK_dbName_';
private static $port = _tK_port_;
private static $encoding = 'utf8mb4';
private static $collation = 'utf8mb4_general_ci';
private static $prefix = '_tK_prefix_';
private function __construct(){
private function __construct()
{
}
public static function illuminate(): Capsule
{
if(self::$uIlluminate !== null){
return self::$uIlluminate;
}
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => self::$host,
'database' => self::$dbName,
'username' => self::$user,
'password' => self::$password,
'charset' => self::$encoding,
'collation' => self::$collation,
]);
$capsule->setEventDispatcher(new Dispatcher(new Container));
$capsule->setAsGlobal();
$capsule->bootEloquent();
self::$uIlluminate = $capsule;
return $capsule;
}
/**
@@ -23,12 +56,14 @@ class DB{
* @return \MeekroDB
* @suppress PhanTypeMismatchProperty
*/
public static function db(){
if(self::$uDB === null){
self::$uDB = new \MeekroDB(self::$host,self::$user,self::$password,self::$dbName,self::$port,self::$encoding);
public static function db()
{
if (self::$uDB === null) {
self::$uDB = new \MeekroDB(self::$host, self::$user, self::$password, self::$dbName, self::$port, self::$encoding);
self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
self::$uDB->error_handler= function(){};
self::$uDB->error_handler = function () {
};
self::$uDB->throw_exception_on_error = true;
self::$uDB->throw_exception_on_nonsql_error = true;
}
@@ -39,4 +74,4 @@ class DB{
{
return self::$prefix;
}
}
}
+298 -54
View File
@@ -2,6 +2,7 @@
namespace sammo;
use DateTime;
use sammo\Event\Action;
require_once 'process_war.php';
@@ -189,7 +190,7 @@ function myNationInfo(General $generalObj)
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
$nationID = $generalObj->getNationID();
$nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation = %i', $nationID)??getNationStaticInfo(0);
$nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation = %i', $nationID) ?? getNationStaticInfo(0);
$city = $db->queryFirstRow(
'SELECT COUNT(*) as cnt, SUM(pop) as totpop, SUM(pop_max) as maxpop from city where nation=%i',
$nationID
@@ -198,16 +199,16 @@ function myNationInfo(General $generalObj)
$topChiefs = Util::convertArrayToDict($db->query('SELECT officer_level, no, name, npc FROM general WHERE nation = %i AND officer_level >= 11', $nationID), 'officer_level');
$level12Name = key_exists(12, $topChiefs)?getColoredName($topChiefs[12]['name'], $topChiefs[12]['npc']):'-';
$level11Name = key_exists(11, $topChiefs)?getColoredName($topChiefs[11]['name'], $topChiefs[11]['npc']):'-';
$level12Name = key_exists(12, $topChiefs) ? getColoredName($topChiefs[12]['name'], $topChiefs[12]['npc']) : '-';
$level11Name = key_exists(11, $topChiefs) ? getColoredName($topChiefs[11]['name'], $topChiefs[11]['npc']) : '-';
$impossibleStrategicCommandLists = [];
$strategicCommandLists = GameConst::$availableChiefCommand['전략'];
$yearMonth = Util::joinYearMonth($admin['year'], $admin['month']);
foreach($strategicCommandLists as $command){
foreach ($strategicCommandLists as $command) {
$cmd = buildNationCommandClass($command, $generalObj, $admin, new LastTurn());
$nextAvailableTurn = $cmd->getNextAvailableTurn();
if($nextAvailableTurn > $yearMonth){
if ($nextAvailableTurn > $yearMonth) {
$impossibleStrategicCommandLists[] = [$cmd->getName(), $nextAvailableTurn - $yearMonth];
}
}
@@ -239,28 +240,28 @@ function myNationInfo(General $generalObj)
<tr>
<td class='bg1 center'><b>총주민</b></td>
<td class='center'>";
echo $nationID===0 ? "해당 없음" : "{$city['totpop']}/{$city['maxpop']}";
echo $nationID === 0 ? "해당 없음" : "{$city['totpop']}/{$city['maxpop']}";
echo "</td>
<td class='bg1 center'><b>총병사</b></td>
<td class='center'>";
echo $nationID===0 ? "해당 없음" : "{$general['totcrew']}/{$general['maxcrew']}";
echo $nationID === 0 ? "해당 없음" : "{$general['totcrew']}/{$general['maxcrew']}";
echo "</td>
</td>
</tr>
<tr>
<td class='bg1 center'><b>국 고</b></td>
<td class='center'>";
echo $nationID===0 ? "해당 없음" : "{$nation['gold']}";
echo $nationID === 0 ? "해당 없음" : "{$nation['gold']}";
echo "</td>
<td class='bg1 center'><b>병 량</b></td>
<td class='center'>";
echo $nationID===0 ? "해당 없음" : "{$nation['rice']}";
echo $nationID === 0 ? "해당 없음" : "{$nation['rice']}";
echo "</td>
</tr>
<tr>
<td class='bg1 center'><b>지급률</b></td>
<td class='center'>";
if ($nationID===0) {
if ($nationID === 0) {
echo "해당 없음";
} else {
echo $nation['bill'] == 0 ? "0 %" : "{$nation['bill']} %";
@@ -269,7 +270,7 @@ function myNationInfo(General $generalObj)
</td>
<td class='bg1 center'><b>세 율</b></td>
<td class='center'>";
if ($nationID===0) {
if ($nationID === 0) {
echo "해당 없음";
} else {
echo $nation['rate'] == 0 ? "0 %" : "{$nation['rate']} %";
@@ -285,7 +286,7 @@ function myNationInfo(General $generalObj)
$nation['tech'] = "$techCall / {$nation['tech']}";
if ($nationID===0) {
if ($nationID === 0) {
$nation['strategic_cmd_limit'] = "<font color=white>해당 없음</font>";
$nation['surlimit'] = "<font color=white>해당 없음</font>";
$nation['scout'] = "<font color=white>해당 없음</font>";
@@ -294,20 +295,20 @@ function myNationInfo(General $generalObj)
} else {
if ($nation['strategic_cmd_limit'] != 0) {
$nation['strategic_cmd_limit'] = "<font color=red>{$nation['strategic_cmd_limit']}턴</font>";
} else if($impossibleStrategicCommandLists) {
} else if ($impossibleStrategicCommandLists) {
$nation['strategic_cmd_limit'] = "<font color=yellow>가 능</font>";
} else{
} else {
$nation['strategic_cmd_limit'] = "<font color=limegreen>가 능</font>";
}
if($impossibleStrategicCommandLists){
if ($impossibleStrategicCommandLists) {
$text = [];
foreach($impossibleStrategicCommandLists as [$cmdName, $remainTurn]){
foreach ($impossibleStrategicCommandLists as [$cmdName, $remainTurn]) {
$text[] = "{$cmdName}: {$remainTurn}턴 뒤";
}
$nation['strategic_cmd_limit'] = $templates->render('tooltip', [
'text'=>'<span style="text-decoration:underline dashed;">'.$nation['strategic_cmd_limit'].'</span>',
'info'=>'<span class="text-left d-inline-block">'.join('<br>', $text).'</span>',
'text' => '<span style="text-decoration:underline dashed;">' . $nation['strategic_cmd_limit'] . '</span>',
'info' => '<span class="text-left d-inline-block">' . join('<br>', $text) . '</span>',
]);
}
@@ -336,11 +337,11 @@ function myNationInfo(General $generalObj)
<tr>
<td style='text-align:center;' class='bg1'><b>속 령</b></td>
<td style='text-align:center;'>";
echo $nationID===0 ? "-" : "{$city['cnt']}";
echo $nationID === 0 ? "-" : "{$city['cnt']}";
echo "</td>
<td style='text-align:center;' class='bg1'><b>장 수</b></td>
<td style='text-align:center;'>";
echo $nationID===0 ? "-" : "{$general['cnt']}";
echo $nationID === 0 ? "-" : "{$general['cnt']}";
echo "</td>
</tr>
<tr>
@@ -348,7 +349,7 @@ function myNationInfo(General $generalObj)
<td style='text-align:center;'>{$nation['power']}</td>
<td style='text-align:center;' class='bg1'><b>기술력</b></td>
<td style='text-align:center;'>";
echo $nationID===0 ? "-" : "{$nation['tech']}";
echo $nationID === 0 ? "-" : "{$nation['tech']}";
echo "</td>
</tr>
<tr>
@@ -904,7 +905,7 @@ function nationMsg(General $general)
$nationID = $general->getNationID();
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
return $nationStor->notice??'';
return $nationStor->notice ?? '';
}
function banner()
@@ -1227,13 +1228,13 @@ function updateOnline()
$onlineNum = count($onlineUser);
$onlineNationUsers = Util::arrayGroupBy($onlineUser, 'nation');
uasort($onlineNationUsers, function(array $lhs, array $rhs){
return -(count($lhs)<=>count($rhs));
uasort($onlineNationUsers, function (array $lhs, array $rhs) {
return - (count($lhs) <=> count($rhs));
});
$onlineNation = [];
foreach($onlineNationUsers as $nationID=>$rawOnlineUser){
foreach ($onlineNationUsers as $nationID => $rawOnlineUser) {
$nationName = getNationStaticInfo($nationID)['name'];
$onlineNation[] = "【{$nationName}】";
$userList = join(', ', Util::squeezeFromArray($rawOnlineUser, 'name'));
@@ -1255,9 +1256,12 @@ function addAge()
//나이와 호봉 증가
$db->update('general', [
'age' => $db->sqleval('age+1'),
'belong' => $db->sqleval('belong+1')
], true);
$db->update('general', [
'belong' => $db->sqleval('belong+1')
], 'nation != 0');
[$startYear, $year, $month] = $gameStor->getValuesAsArray(['startyear', 'year', 'month']);
if ($year >= $startYear + 3) {
@@ -1265,7 +1269,7 @@ function addAge()
$generalID = $general['no'];
$special = SpecialityHelper::pickSpecialDomestic(
$general,
(Json::decode($general['aux'])['prev_types_special'])??[]
(Json::decode($general['aux'])['prev_types_special']) ?? []
);
$specialClass = buildGeneralSpecialDomesticClass($special);
$specialText = $specialClass->getName();
@@ -1282,16 +1286,25 @@ function addAge()
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,npc,dex1,dex2,dex3,dex4,dex5,aux from general where specage2<=age and special2=%s', GameConst::$defaultSpecialWar) as $general) {
$generalID = $general['no'];
$special2 = SpecialityHelper::pickSpecialWar(
$general,
(Json::decode($general['aux'])['prev_types_special2'])??[]
);
$generalAux = Json::decode($general['aux']);
$updateVars = [];
if (key_exists('inheritSpecificSpecialWar', $generalAux)) {
$special2 = $generalAux['inheritSpecificSpecialWar'];
unset($generalAux['inheritSpecificSpecialWar']);
$updateVars['aux'] = Json::encode($generalAux);
} else {
$special2 = SpecialityHelper::pickSpecialWar(
$general,
($generalAux['prev_types_special2']) ?? []
);
}
$specialClass = buildGeneralSpecialWarClass($special2);
$specialText = $specialClass->getName();
$db->update('general', [
'special2' => $special2
], 'no=%i', $general['no']);
$updateVars['special2'] = $special2;
$db->update('general', $updateVars, 'no=%i', $general['no']);
$logger = new ActionLogger($generalID, $general['nation'], $year, $month);
@@ -1537,15 +1550,15 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
$occupiedUnique = [];
$invalidItemType = [];
foreach(array_keys(GameConst::$allItems) as $itemType){
$ownItem = $general->getItems()[$itemType]??null;
if($ownItem !== null && !$ownItem->isBuyable()){
foreach (array_keys(GameConst::$allItems) as $itemType) {
$ownItem = $general->getItems()[$itemType] ?? null;
if ($ownItem !== null && !$ownItem->isBuyable()) {
$invalidItemType[$itemType] = true;
}
}
foreach (array_keys(GameConst::$allItems) as $itemType) {
if(key_exists($itemType, $invalidItemType)){
if (key_exists($itemType, $invalidItemType)) {
continue;
}
foreach ($db->queryAllLists('SELECT %b, count(*) as cnt FROM general GROUP BY %b', $itemType, $itemType) as [$itemCode, $cnt]) {
@@ -1561,11 +1574,11 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
}
foreach (GameConst::$allItems as $itemType => $itemCategories) {
if(key_exists($itemType, $invalidItemType)){
if (key_exists($itemType, $invalidItemType)) {
continue;
}
foreach ($itemCategories as $itemCode => $cnt) {
if($cnt == 0){
if ($cnt == 0) {
continue;
}
if (!key_exists($itemCode, $occupiedUnique)) {
@@ -1581,9 +1594,19 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
}
if (!$availableUnique) {
if ($general->getAuxVar('inheritRandomUnique')) {
$general->setAuxVar('inheritRandomUnique', null);
$general->increaseInheritancePoint('previous', GameConst::$inheritItemRandomPoint);
$userLogger = new UserLogger($general->getVar('owner'));
$userLogger->push(sprintf("얻을 유니크가 없어 %d 포인트 반환", GameConst::$inheritItemRandomPoint), "inheritPoint");
}
return false;
}
if ($general->getAuxVar('inheritRandomUnique')) {
$general->setAuxVar('inheritRandomUnique', null);
}
[$itemType, $itemCode] = Util::choiceRandomUsingWeightPair($availableUnique);
$nationName = $general->getStaticNation()['name'];
@@ -1607,6 +1630,207 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
return true;
}
function rollbackInheritUniqueTrial(General $general, string $itemKey, string $reason)
{
$ownerID = $general->getVar('owner');
$db = DB::db();
$itemTrials = $general->getAuxVar('inheritUniqueTrial');
LogText("선택유니크 롤백:{$ownerID}", [$itemKey, $itemTrials]);
unset($itemTrials[$itemKey]);
if(count($itemTrials) == 0){
$itemTrials = null;
}
$general->setAuxVar('inheritUniqueTrial', $itemTrials);
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}");
$ownTrial = $trialStor->getValue("u{$ownerID}");
$itemObj = buildItemClass($itemKey);
$itemName = $itemObj->getName();
if ($ownTrial) {
//두 값이 general, KVStorage 둘다 있고, 이중에선 KVStorage 값을 기준으로 하자 따르자
[,, $amount] = $ownTrial;
$trialStor->deleteValue("u{$ownerID}");
$general->increaseInheritancePoint('previous', $amount);
LogText("선택유니크 롤백포인트:{$ownerID}", $amount);
$userLogger = new UserLogger($ownerID);
$userLogger->push("{$itemName} 입찰에 사용한 {$amount} 포인트 반환", "inheritPoint");
}
//메시지
$staticNation = $general->getStaticNation();
$unlimited = new \DateTime('9999-12-31');
$src = new MessageTarget(0, '', 0, 'System', '#000000');
$dest = new MessageTarget($general->getID(), $general->getName(), $general->getNationID(), $staticNation['name'], $staticNation['color'], GetImageURL($general->getVar('imgsvr'), $general->getVar('picture')));
$josaUl = JosaUtil::pick($itemName, '을');
$msg = new Message(
Message::MSGTYPE_PRIVATE,
$src,
$dest,
"{$itemName}{$josaUl} 얻지 못했습니다. {$reason}",
new DateTime(),
$unlimited,
[]
);
$general->applyDB($db);
$msg->send(true);
}
function tryRollbackInheritUniqueItem(General $general): void
{
tryInheritUniqueItem($general, 'Rollback', true);
}
function tryInheritUniqueItem(General $general, string $acquireType = '아이템', bool $justRollback = false): bool
{
$ownerID = $general->getVar('owner');
if (!$ownerID) {
LogText("선택유니크 실패???: {$ownerID}", $general->getName());
return false;
}
$itemTrials = $general->getAuxVar('inheritUniqueTrial') ?? [];
arsort($itemTrials);
LogText("선택유니크항목: {$ownerID}", $itemTrials);
$db = DB::db();
$ownTarget = null;
$ownType = null;
foreach ($itemTrials as $itemKey => $amount) {
$availableItemTypes = [];
$reasons = [];
foreach (GameConst::$allItems as $itemType => $itemList) {
//아직은 그런 경우는 없지만 동일 유니크를 여러 부위에 장착할 수 있을지도 모름
if (!key_exists($itemKey, $itemList)) {
continue;
}
$ownItem = $general->getItem($itemType);
if ($ownItem->getRawClassName() == $itemKey) {
$reasons[] = '이미 그 유니크를 가지고 있습니다.';
continue;
}
/*
if (!$ownItem->isBuyable()) {
$reasons[] = '이미 다른 유니크를 가지고 있습니다.';
continue;
}
*/
$availableCnt = $itemList[$itemKey];
$occupiedCnt = $db->queryFirstField('SELECT count(*) FROM general WHERE %b = %s', $itemType, $itemKey);
if ($occupiedCnt >= $availableCnt) {
$reasons[] = '그 유니크는 모두 점유되었습니다.';
continue;
}
$availableItemTypes[] = $itemType;
}
if (!$availableItemTypes) {
rollbackInheritUniqueTrial($general, $itemKey, join(' ', $reasons));
continue;
}
$reasons = [];
$itemType = Util::choiceRandom($availableItemTypes);
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}"); //혹시 itemKey의 크기가 37이 넘을 수 있을까?
$anyTrials = $trialStor->getAll();
if (!$anyTrials) {
//순서가 꼬였던 모양, 실제 값은 storage를 우선시하자
rollbackInheritUniqueTrial($general, $itemKey, '절차상의 오류입니다.');
continue;
}
//XXX: 정렬할 필요 없지 않나?
usort($anyTrials, function ($lhsTrial, $rhsTrial) {
[,, $lhsAmount] = $lhsTrial;
[,, $rhsAmount] = $rhsTrial;
return $rhsAmount <=> $lhsAmount; //큰 값이 앞에 오도록
});
LogText("선택유니크상태 {$ownerID} {$itemKey}", $anyTrials);
//공동 1등인데 본인이 있을 수도 있다.
[,, $topAmount] = $anyTrials[0];
if ($amount < $topAmount) {
$compAmount = $topAmount / $amount;
if ($compAmount > 2.0) {
$compText = '엄청난 차이로 ';
} else if ($compAmount > 1.2) {
$compText = '큰 차이로 ';
} else if ($compAmount > 1.05) {
$compText = '';
} else {
$compText = '아슬아슬한 차이로 ';
}
rollbackInheritUniqueTrial($general, $itemKey, "{$compText}상위 입찰한 장수가 있습니다.");
continue;
}
//내가 1위다
if ($ownTarget !== null) {
//이미 다른 아이템을 얻기로 되어있다.
continue;
}
$ownTarget = $itemKey;
$ownType = $itemType;
}
unset($itemKey);
unset($itemType);
if ($ownTarget === null) {
return false;
}
if ($justRollback) {
return false;
}
LogText("선택유니크획득{$ownerID}", $ownTarget);
$trialStor = KVStorage::getStorage($db, "ut_{$ownTarget}");
$trialStor->deleteValue("u{$ownerID}");
//rollbackInheritUniqueTrial 과정 때문에 새로 받아와야함
$itemTrials = $general->getAuxVar('inheritUniqueTrial');
unset($itemTrials[$ownTarget]);
$general->setAuxVar('inheritUniqueTrial', $itemTrials);
$nationName = $general->getStaticNation()['name'];
$generalName = $general->getName();
$josaYi = JosaUtil::pick($generalName, '이');
$itemObj = buildItemClass($ownTarget);
$itemName = $itemObj->getName();
$itemRawName = $itemObj->getRawName();
$josaUl = JosaUtil::pick($itemRawName, '을');
$general->setVar($ownType, $ownTarget);
$logger = $general->getLogger();
$logger->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 습득했습니다!");
$logger->pushGeneralHistoryLog("<C>{$itemName}</>{$josaUl} 습득");
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
$logger->pushGlobalHistoryLog("<C><b>【{$acquireType}】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
$general->applyDB($db);
return true;
}
function tryUniqueItemLottery(General $general, string $acquireType = '아이템'): bool
{
$db = DB::db();
@@ -1616,8 +1840,13 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
return false;
}
if ($general->getNPCType() > 6) {
return false;
$inheritUnique = $general->getAuxVar('inheritUniqueTrial');
if ($acquireType != '설문조사' && $inheritUnique && count($inheritUnique)) {
LogText("유니크 준비?? {$general->getID()}", $inheritUnique);
$trialResult = tryInheritUniqueItem($general, $acquireType);
if ($trialResult) {
return true;
}
}
$itemTypeCnt = count(GameConst::$allItems);
@@ -1629,8 +1858,14 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
}
}
if($trialCnt <= 0){
if ($trialCnt <= 0) {
LogText("{$general->getName()}, {$general->getID()} 모든 아이템", $trialCnt);
if ($general->getAuxVar('inheritRandomUnique')) {
$general->setAuxVar('inheritRandomUnique', null);
$general->increaseInheritancePoint('previous', GameConst::$inheritItemRandomPoint);
$userLogger = new UserLogger($general->getVar('owner'));
$userLogger->push(sprintf("유니크를 얻을 공간이 없어 %d 포인트 반환", GameConst::$inheritItemRandomPoint), "inheritPoint");
}
return false;
}
@@ -1653,18 +1888,25 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
$prob = 1 / ($genCount * $itemTypeCnt / 10 / 4); // 건국시 4개(20%) 등장(200명시 20국 정도 됨)
}
$prob = Util::valueFit($prob, null, 1 / 4);//최대치 감소
$prob = Util::valueFit($prob, null, 1 / 4); //최대치 감소
$result = false;
$prob /= sqrt(2);
$moreProb = pow(2, 1 / 4);
if ($general->getAuxVar('inheritRandomUnique')) {
//포인트로 랜덤 유니크 획득
$prob = 1;
}
foreach(Util::range($trialCnt) as $_idx){
foreach (Util::range($trialCnt) as $_idx) {
if (Util::randBool($prob)) {
$result = true;
break;
}
$prob *= $moreProb;
}
if(!$result){
if (!$result) {
LogText("{$general->getName()}, {$general->getID()} 유니크 실패 {$trialCnt}", $prob);
return false;
}
@@ -1681,7 +1923,7 @@ function getAdmin()
}
/** @return General[] */
function deleteNation(General $lord, bool $applyDB):array
function deleteNation(General $lord, bool $applyDB): array
{
$lordID = $lord->getID();
$nationID = $lord->getNationID();
@@ -1706,7 +1948,8 @@ function deleteNation(General $lord, bool $applyDB):array
$nationID,
$lordID
),
['npc', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'], 1
['npc', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'],
1
);
$nationGeneralList[$lordID] = $lord;
@@ -1722,11 +1965,12 @@ function deleteNation(General $lord, bool $applyDB):array
$destroyHistoryLog = "<D><b>{$nationName}</b></>{$josaYi} <R>멸망</>";
// 전 장수 재야로
foreach($nationGeneralList as $general){
$general->setAuxVar('max_belong',
foreach ($nationGeneralList as $general) {
$general->setAuxVar(
'max_belong',
max(
$general->getVar('belong'),
$general->getAuxVar('max_belong')??0
$general->getAuxVar('max_belong') ?? 0
)
);
$general->setVar('belong', 0);
@@ -1739,7 +1983,7 @@ function deleteNation(General $lord, bool $applyDB):array
$logger->pushGeneralActionLog($destroyLog, ActionLogger::PLAIN);
$logger->pushGeneralHistoryLog($destroyHistoryLog);
if($applyDB){
if ($applyDB) {
$general->applyDB($db);
}
}
@@ -2158,7 +2402,7 @@ function getRandTurn($term, ?\DateTimeInterface $baseDateTime = null)
$randSecond = Util::randRangeInt(0, 60 * $term - 1);
$randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수
return $baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s');
return TimeUtil::format($baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction)), true);
}
function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null)
@@ -2173,5 +2417,5 @@ function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null)
$randSecond = Util::randRangeInt(0, 60 * $term - 1);
$randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수
return $baseDateTime->sub(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s');
return $baseDateTime->sub(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s.u');
}
+37 -12
View File
@@ -1,4 +1,4 @@
<?php
<?php
namespace sammo;
@@ -6,7 +6,7 @@ use sammo\Command\BaseCommand;
/**
* Value Converter
*
*
* Side effect 없이 값의 변환만을 수행하는 함수들의 모음.
* (단, autoload, 정적 변수 초기화는 허용)
*/
@@ -175,7 +175,7 @@ function buildNationTypeClass(?string $type):BaseNation{
return $cache[$type];
}
$class = getNationTypeClass($type);
$obj = new $class();
$cache[$type]= $obj;
return $obj;
@@ -241,7 +241,7 @@ function buildItemClass(?string $type):BaseItem{
return $cache[$type];
}
$class = getItemClass($type);
$obj = new $class();
$cache[$type]= $obj;
return $obj;
@@ -276,7 +276,7 @@ function buildGeneralSpecialDomesticClass(?string $type):BaseSpecial{
return $cache[$type];
}
$class = getGeneralSpecialDomesticClass($type);
$obj = new $class();
$cache[$type]= $obj;
return $obj;
@@ -311,7 +311,7 @@ function buildGeneralSpecialWarClass(?string $type):BaseSpecial{
return $cache[$type];
}
$class = getGeneralSpecialWarClass($type);
$obj = new $class();
$cache[$type]= $obj;
return $obj;
@@ -357,6 +357,31 @@ function buildNationCommandClass(?string $type, General $generalObj, array $env,
return new $class($generalObj, $env, $lastTurn, $arg);
}
function getAPIExecutorClass($path){
static $basePath = __NAMESPACE__.'\\API\\';
if(is_string($path)){
}
else if(is_array($path)){
$path = join('\\', $path);
}
else{
throw new \InvalidArgumentException("{$path}는 올바른 API 지시자가 아님");
}
$classPath = str_replace('/', '\\', $basePath.$path);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$path}는 올바른 API 경로가 아님");
}
function buildAPIExecutorClass($type, string $rootPath, array $args):\sammo\BaseAPI{
$class = getAPIExecutorClass($type);
return new $class($rootPath, $args);
}
function getWarUnitTriggerClass(string $type){
static $basePath = __NAMESPACE__.'\\WarUnitTrigger\\';
$classPath = ($basePath.$type);
@@ -391,8 +416,8 @@ function getGeneralPoolClass(string $type){
/**
* @param \MeekroDB $db
* @param int $owner
* @param int $pickCnt
* @param int $owner
* @param int $pickCnt
* @param null|string $prefix
* @return AbsGeneralPool[]
*/
@@ -538,8 +563,8 @@ function getExpLevel($experience) {
function getDedLevel($dedication) {
$level = Util::valueFit(
ceil(sqrt($dedication) / 10),
0,
ceil(sqrt($dedication) / 10),
0,
GameConst::$maxDedLevel
);
@@ -572,7 +597,7 @@ function getCost(int $armtype) : int {
function getTechLevel($tech):int{
return Util::valueFit(
floor($tech / 1000),
0,
0,
GameConst::$maxTechLevel
);
}
@@ -583,7 +608,7 @@ function TechLimit($startYear, $year, $tech) : bool {
$relMaxTech = Util::valueFit(
floor($relYear / 5) + 1,
1,
1,
GameConst::$maxTechLevel
);
+24 -4
View File
@@ -623,7 +623,7 @@ function updateNationState()
$nation['nation'],
$targetKillTurn
);
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc'], 2);
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux'], 2);
$chiefObj = null;
$uniqueLotteryWeightList = [];
@@ -1150,22 +1150,42 @@ function checkEmperior()
LogHistory();
}
function resetInheritanceUser(int $userID, bool $isRebirth=false){
function resetInheritanceUser(int $userID, bool $isRebirth=false):float{
$rebirthDegraded = [
'dex'=>0.5,
];
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}");
$totalPoint = 0;
foreach($inheritStor->getAll() as $key=>[$value,]){
if(key_exists($key, $rebirthDegraded)){
$allPoints = $inheritStor->getAll();
if(!$allPoints || count($allPoints) == 0){
//비었으므로 리셋 안함
return 0;
}
if(count($allPoints) == 1 && key_exists('previous', $allPoints)){
//이미 리셋되었으므로 리셋 안함
return $allPoints['previous'][0];
}
$userLogger = new UserLogger($userID);
$previousPoint = ($allPoints['previous']??[0,0])[0];
foreach($allPoints as $key=>[$value,]){
if($isRebirth && key_exists($key, $rebirthDegraded)){
$value *= $rebirthDegraded[$key];
}
$keyText = General::INHERITANCE_KEY[$key][2];
$userLogger->push("{$keyText} 포인트 {$value} 증가", "inheritPoint");
$totalPoint += $value;
}
$totalPoint = Util::toInt($totalPoint);
$userLogger->push("포인트 {$previousPoint} => {$totalPoint}", "inheritPoint");
$userLogger->flush();
$inheritStor->resetValues();
$inheritStor->setValue('previous', [$totalPoint, null]);
return $totalPoint;
}
function updateMaxDomesticCritical(General $general, $score){
+5 -5
View File
@@ -47,7 +47,7 @@ else{
'name', 'leadership', 'strength', 'intel', 'gold','rice',
'troop','officer_level','npc','picture','imgsvr',
'permission','penalty','belong', 'crewtype',
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit',
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'aux',
], 1);
if($general instanceof DummyGeneral){
@@ -104,7 +104,7 @@ function do수뇌임명(General $general, int $targetOfficerLevel):?string{
if($general->getVar('strength') < GameConst::$chiefStatMin){
return '무력이 부족합니다.';
}
}
else{
if($general->getVar('intel') < GameConst::$chiefStatMin){
@@ -175,7 +175,7 @@ function do추방(General $general, int $myOfficerLevel):?string{
$generalName = $general->getVar('name');
$nationID = $general->getNationID();
//추방할사람이 외교권자이면 불가
$permission = checkSecretPermission($general->getRaw());
@@ -252,7 +252,7 @@ function do추방(General $general, int $myOfficerLevel):?string{
]);
$src = new MessageTarget(
$generalID,
$generalID,
$generalName,
$nationID,
$nation['name'],
@@ -260,7 +260,7 @@ function do추방(General $general, int $myOfficerLevel):?string{
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
);
$msg = new Message(
Message::MSGTYPE_PUBLIC,
Message::MSGTYPE_PUBLIC,
$src,
$src,
$str,
+3 -9
View File
@@ -39,7 +39,7 @@ $db = DB::db();
$me = General::createGeneralObjFromDB($generalID);
if($defence_train != $me->getVar('defence_train')){
if($defence_train !== $me->getVar('defence_train')){
if($defence_train == 999){
$me->increaseVar('myset', -1);
$me->setVar('defence_train', $defence_train);
@@ -53,14 +53,8 @@ if($defence_train != $me->getVar('defence_train')){
}
$me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100));
if($use_auto_nation_turn != $me->getAuxVar('use_auto_nation_turn')){
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
}
if($me->getVar('tnmt') != $tnmt){
$me->setVar('tnmt', $tnmt);
}
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
$me->setVar('tnmt', $tnmt);
if($me->getNPCType() == 1 && $detachNPC){
$turnterm = $gameStor->turnterm;
-182
View File
@@ -1,182 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$session = Session::requireLogin()->setReadOnly();
$userID = Session::getUserID();
if (!$userID) {
MessageBox("잘못된 접근입니다!!!");
echo "<script>history.go(-1);</script>";
exit(1);
}
//회원 테이블에서 정보확인
$member = RootDB::db()->queryFirstRow("select no,name,picture,imgsvr,grade from member where no= %i", $userID);
if (!$member) {
MessageBox("잘못된 접근입니다!!!");
echo "<script>history.go(-1);</script>";
exit(1);
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['block_general_create','show_img_level','maxgeneral']);
if($admin['block_general_create']){
MessageBox("잘못된 접근입니다!!!");
echo "<script>history.go(-1);</script>";
exit(1);
}
?>
<!DOCTYPE html>
<html>
<head>
<title><?=UniqueConst::$serverName?>: 장수생성</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<script>
var defaultStatTotal = <?=GameConst::$defaultStatTotal?>;
var defaultStatMin = <?=GameConst::$defaultStatMin?>;
var defaultStatMax = <?=GameConst::$defaultStatMax?>;
var charInfoText = <?php
$charInfoText = [];
foreach(GameConst::$availablePersonality as $personalityID){
$personalityInfo = buildPersonalityClass($personalityID)->getInfo();
$charInfoText[$personalityID] = $personalityInfo;
}
echo Json::encode((object)$charInfoText);
?>;
</script>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printJS('dist_js/join.js')?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td>장 수 생 성<br><?=backButton()?></td></tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td align=center><?=info(0)?></td></tr>
</table>
<?php
$gencount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc<2');
if ($gencount >= $admin['maxgeneral']) {
echo "<script>alert('더 이상 등록할 수 없습니다.');</script>";
echo "<script>history.go(-1);</script>";
exit();
}
$nationList = $db->query('SELECT nation,`name`,color,scout FROM nation');
shuffle($nationList);
$nationList = Util::convertArrayToDict($nationList, 'nation');
//NOTE: join 안할것임
$scoutMsgs = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'scout_msg');
foreach($scoutMsgs as $nationID=>$scoutMsg){
$nationList[$nationID]['scoutmsg'] = $scoutMsg;
}
echo getInvitationList($nationList);
?>
<form id='join_form' name=form1 method=post action=join_post.php>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td colspan=3 align=center class='bg1'>장수 생성</td>
</tr>
<tr>
<td width=498 align=right class='bg1'>장수명</td>
<td colspan=2>
<input id="generalName" type=text name=name maxlength=18 size=18 style="color:white;background-color:black;" value="<?=$member['name']?>">(전각 9글자, 반각 18글자 이내)
</td>
</tr>
<?php
if ($admin['show_img_level'] >= 1 && $member['grade'] >= 1 && $member['picture'] != "") {
$imageTemp = GetImageURL($member['imgsvr']);
echo "
<tr>
<td align=right class='bg1'>전콘 사용 여부</td>
<td width=64 height=64>
<img width='64' height='64' src='{$imageTemp}/{$member['picture']}' border='0'>
</td>
<td>
<input type=checkbox name=pic value=1 checked>사용
</td>
</tr>
";
}
?>
<tr>
<td align=center colspan=3>
계정관리에서 자신만을 표현할 수 있는 아이콘을 업로드 해보세요!
</td>
</tr>
<tr>
<td width=498 align=right class='bg1'>성격</td>
<td colspan=2>
<select id="selChar" name=character size=1 maxlength=15 style=color:white;background-color:black;>
<option selected value='Random'>????</option>
<?php foreach(GameConst::$availablePersonality as $personalityID): ?>
<?php $personalityName = buildPersonalityClass($personalityID)->getName(); ?>
<option value='<?=$personalityID?>'><?=$personalityName?></option>
<?php endforeach; ?>
</select> <span id="charInfoText"></span>
</td>
</tr>
<tr>
<td width=498 align=right class='bg1'>통솔</td>
<td colspan=2><input type="number" name="leadership" id="leadership" value="50"></td>
</tr>
<tr>
<td width=498 align=right class='bg1'>무력</td>
<td colspan=2><input type="number" name="strength" id="strength" value="50"></td>
</tr>
<tr>
<td width=498 align=right class='bg1'>지력</td>
<td colspan=2><input type="number" name="intel" id="intel" value="50"></td>
</tr>
<tr>
<td width=498 align=right class='bg1'>능력치 조정</td>
<td colspan=2>
<input type=button value=랜덤형 onclick=abilityRand()>
<input type=button value=통솔무력형 onclick=abilityLeadpow()>
<input type=button value=통솔지력형 onclick=abilityLeadint()>
<input type=button value=무력지력형 onclick=abilityPowint()>
</td>
</tr>
<tr>
<td align=center colspan=3>
<font color=orange>모든 능력치는 ( <?=GameConst::$defaultStatMin?> <= 능력치 <= <?=GameConst::$defaultStatMax?> ) 사이로 잡으셔야 합니다.<br>
그 외의 능력치는 가입되지 않습니다.</font>
</td>
</tr>
<tr>
<td align=center colspan=3>
능력치의 총합은 <?=GameConst::$defaultStatTotal?>입니다. 가입후 0~10의 능력치 보너스를 받게 됩니다.<br>
임의의 도시에서 재야로 시작하며 건국과 임관은 게임 내에서 실행합니다.
</td>
</tr>
<tr>
<td width=498 align=right><input type=submit name=join value=장수생성></td>
<td colspan=2><input type=reset name=reset value=다시입력></td>
</tr>
</table>
</form>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?> </td></tr>
</table>
</body>
</html>
-341
View File
@@ -1,341 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$v = new Validator($_POST);
$v
->rule('required', [
'name',
'leadership',
'strength',
'intel'
])
->rule('integer', [
'leadership',
'strength',
'intel',
])
->rule('stringWidthBetween', 'name', 1, 18)
->rule('min', [
'leadership',
'strength',
'intel'
], GameConst::$defaultStatMin)
->rule('max', [
'leadership',
'strength',
'intel'
], GameConst::$defaultStatMax)
->rule('in', 'character', array_merge(GameConst::$availablePersonality, ['Random']));
if (!$v->validate()) {
MessageBox($v->errorStr());
echo "<script>history.go(-1);</script>";
exit(1);
}
$session = Session::requireLogin()->setReadOnly();
$userID = Session::getUserID();
//NOTE: 이 페이지에서는 세션에 데이터를 등록하지 않음. 로그인은 이후에.
$name = Util::getPost('name');
$name = htmlspecialchars($name);
$name = StringUtil::removeSpecialCharacter($name);
$name = WebUtil::htmlPurify($name);
$name = StringUtil::textStrip($name);
$pic = (int)Util::getPost('pic', 'bool', 0);
$character = Util::getPost('character');
$leadership = Util::getPost('leadership', 'int', 50);
$strength = Util::getPost('strength', 'int', 50);
$intel = Util::getPost('intel', 'int', 50);
$join = Util::getPost('join'); //쓸모 없음
$rootDB = RootDB::db();
//회원 테이블에서 정보확인
$member = $rootDB->queryFirstRow('SELECT `no`, id, picture, grade, `name`, imgsvr FROM member WHERE no=%i', $userID);
if (!$member) {
MessageBox("잘못된 접근입니다!!!");
echo "<script>history.go(-1);</script>";
exit(1);
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['year','month','maxgeneral','scenario','show_img_level','turnterm','turntime','genius','npcmode']);
########## 동일 정보 존재여부 확인. ##########
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
$oldGeneral = $db->queryFirstField('SELECT `no` FROM general WHERE `owner`=%i', $userID);
$oldName = $db->queryFirstField('SELECT `no` FROM general WHERE `name`=%s', $name);
if ($oldGeneral) {
echo("<script>
window.alert('이미 등록하셨습니다!')
history.go(-1)
</script>");
exit;
}
if ($oldName) {
echo("<script>
window.alert('이미 있는 장수입니다. 다른 이름으로 등록해 주세요!')
history.go(-1)
</script>");
exit;
}
if ($gameStor->maxgeneral <= $gencount) {
echo("<script>
window.alert('더이상 등록할 수 없습니다!')
history.go(-1)
</script>");
exit;
}
if ($name == '') {
echo("<script>
window.alert('이름이 짧습니다. 다시 가입해주세요!')
history.go(-1)
</script>");
exit;
}
if (mb_strwidth($name) > 18) {
echo("<script>
window.alert('이름이 유효하지 않습니다. 다시 가입해주세요!')
history.go(-1)
</script>");
exit;
}
if ($leadership + $strength + $intel > GameConst::$defaultStatTotal) {
echo("<script>
window.alert('능력치가 ".GameConst::$defaultStatTotal."을 넘어섰습니다. 다시 가입해주세요!')
history.go(-1)
</script>");
exit;
}
$genius = Util::randBool(0.01);
// 현재 1%
if ($genius && $gameStor->genius > 0) {
$gameStor->genius = $gameStor->genius-1;
} else {
$genius = false;
}
// 공백지에서만 태어나게
$city = $db->queryFirstField("select city from city where level>=5 and level<=6 and nation=0 order by rand() limit 0,1");
if (!$city) {
$city = $db->queryFirstField("select city from city where level>=5 and level<=6 order by rand() limit 0,1");
}
$pleadership = 0;
$pstrength = 0;
$pintel = 0;
foreach(Util::range(Util::randRangeInt(3, 5)) as $statIdx){
switch (Util::choiceRandomUsingWeight([$leadership, $strength, $intel])) {
case 0:
$pleadership++;
break;
case 1:
$pstrength++;
break;
case 2:
$pintel++;
break;
}
}
$leadership = $leadership + $pleadership;
$strength = $strength + $pstrength;
$intel = $intel + $pintel;
$admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year']);
$relYear = Util::valueFit($admin['year'] - $admin['startyear'], 0);
$age = 20 + ($pleadership + $pstrength + $pintel) * 2 - (mt_rand(0, 1));
// 아직 남았고 천재등록상태이면 특기 부여
if ($genius) {
$specage2 = $age;
$special2 = SpecialityHelper::pickSpecialWar([
'leadership'=>$leadership,
'strength'=>$strength,
'intel'=>$intel,
'dex1'=>0,
'dex2'=>0,
'dex3'=>0,
'dex4'=>0,
'dex5'=>0
]);
} else {
$specage2 = Util::valueFit(Util::round((GameConst::$retirementYear - $age)/6 - $relYear / 2), 3) + $age;
$special2 = GameConst::$defaultSpecialWar;
}
//내특
$specage = Util::valueFit(Util::round((GameConst::$retirementYear - $age)/12 - $relYear / 2), 3) + $age;
$special = GameConst::$defaultSpecialDomestic;
if ($admin['scenario'] >= 1000) {
$specage2 = $age + 3;
$specage = $age + 3;
}
if($relYear < 3){
$experience = 0;
}
else{
$expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 4');
$targetGenOrder = Util::round($expGenCount * 0.2);
$experience = $db->queryFirstField(
'SELECT experience FROM general WHERE nation != 0 AND npc < 4 ORDER BY experience ASC LIMIT %i, 1',
$targetGenOrder - 1
);
$experience *= 0.8;
}
$turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime']));
$now = date('Y-m-d H:i:s');
if ($now >= $turntime) {
$turntime = addTurn($turntime, $admin['turnterm']);
}
//특회 전콘
if ($admin['show_img_level'] >= 1 && $member['grade'] >= 1 && $member['picture'] != "" && $pic) {
$face = $member['picture'];
$imgsvr = $member['imgsvr'];
} else {
$face = "default.jpg";
$imgsvr = 0;
}
//성격 랜덤시
if (!in_array($character, GameConst::$availablePersonality)){
$character = Util::choiceRandom(GameConst::$availablePersonality);
}
//상성 랜덤
$affinity = rand()%150 + 1;
########## 회원정보 테이블에 입력값을 등록한다. ##########
$db->insert('general', [
'owner' => $userID,
'name' => $name,
'owner_name' => $member['name'],
'picture' => $face,
'imgsvr' => $imgsvr,
'nation' => 0,
'city' => $city,
'troop' => 0,
'affinity' => $affinity,
'leadership' => $leadership,
'strength' => $strength,
'intel' => $intel,
'experience' => $experience,
'dedication' => 0,
'gold' => GameConst::$defaultGold,
'rice' => GameConst::$defaultRice,
'crew' => 0,
'train' => 0,
'atmos' => 0,
'officer_level' => 0,
'turntime' => $turntime,
'killturn' => 6,
'lastconnect' => $now,
'lastrefresh' => $now,
'crewtype'=>GameUnitConst::DEFAULT_CREWTYPE,
'makelimit' => 0,
'age' => $age,
'startage' => $age,
'personal' => $character,
'specage' => $specage,
'special' => $special,
'specage2' => $specage2,
'special2' => $special2
]);
$generalID = $db->insertId();
$turnRows = [];
foreach(Util::range(GameConst::$maxTurn) as $turnIdx){
$turnRows[] = [
'general_id'=>$generalID,
'turn_idx'=>$turnIdx,
'action'=>'휴식',
'arg'=>null,
'brief'=>'휴식'
];
}
$db->insert('general_turn', $turnRows);
resetInheritanceUser($userID);
$rank_data = [];
foreach(array_keys(General::RANK_COLUMN) as $rankColumn){
$rank_data[] = [
'general_id'=>$generalID,
'nation_id'=>0,
'type'=>$rankColumn,
'value'=>0
];
}
$db->insert('rank_data', $rank_data);
$db->insert('betting', [
'general_id'=>$generalID,
]);
$cityname = CityConst::byID($city)->name;
$me = [
'no'=>$generalID
];
$log = [];
$mylog = [];
$logger = new ActionLogger($generalID, 0, $gameStor->year, $gameStor->month);
$josaRa = JosaUtil::pick($name, '라');
$speicalText = getGeneralSpecialWarName($special2);
if ($genius) {
$logger->pushGlobalActionLog("<G><b>{$cityname}</b></>에서 <Y>{$name}</>{$josaRa}는 기재가 천하에 이름을 알립니다.");
$logger->pushGlobalActionLog("<C>{$speicalText}</> 특기를 가진 <C>천재</>의 등장으로 온 천하가 떠들썩합니다.");
$logger->pushGlobalHistoryLog("<L><b>【천재】</b></><G><b>{$cityname}</b></>에 천재가 등장했습니다.");
} else {
$logger->pushGlobalActionLog("<G><b>{$cityname}</b></>에서 <Y>{$name}</>{$josaRa}는 호걸이 천하에 이름을 알립니다.");
}
$logger->pushGeneralHistoryLog("<Y>{$name}</>, <G>{$cityname}</>에서 큰 뜻을 품다.");
$logger->pushGeneralActionLog("삼국지 모의전투 PHP의 세계에 오신 것을 환영합니다 ^o^", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("처음 하시는 경우에는 <D>도움말</>을 참고하시고,", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("문의사항이 있으시면 게시판에 글을 남겨주시면 되겠네요~", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("부디 즐거운 삼모전 되시길 바랍니다 ^^", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("통솔 <C>$pleadership</> 무력 <C>$pstrength</> 지력 <C>$pintel</> 의 보너스를 받으셨습니다.", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("연령은 <C>$age</>세로 시작합니다.", ActionLogger::PLAIN);
if ($genius) {
$logger->pushGeneralActionLog("축하합니다! 천재로 태어나 처음부터 <C>{$speicalText}</> 특기를 가지게 됩니다!", ActionLogger::PLAIN);
$logger->pushGeneralHistoryLog("<C>{$speicalText}</> 특기를 가진 천재로 탄생.");
}
$logger->flush();
pushAdminLog(["가입 : {$userID} // {$name} // {$generalID}".getenv("REMOTE_ADDR")]);
$rootDB->insert('member_log', [
'member_no' => $userID,
'date'=>TimeUtil::now(),
'action_type'=>'make_general',
'action'=>Json::encode([
'server'=>DB::prefix(),
'type'=>'general',
'generalID'=>$generalID,
'generalName'=>$name
])
]);
?>
<script>
window.alert('정상적으로 회원 가입되었습니다. 장수명 : <?=$name?> \n위키와 팁/강좌 게시판을 꼭 읽어보세요!');
</script>
<script>location.replace('./');</script>
+444
View File
@@ -0,0 +1,444 @@
<?php
namespace sammo\API\General;
use sammo\ActionLogger;
use sammo\CityConst;
use sammo\DB;
use sammo\GameConst;
use sammo\GameUnitConst;
use sammo\General;
use sammo\JosaUtil;
use sammo\Json;
use sammo\KVStorage;
use sammo\RootDB;
use sammo\Session;
use sammo\SpecialityHelper;
use sammo\StringUtil;
use sammo\TimeUtil;
use sammo\UserLogger;
use sammo\Util;
use sammo\Validator;
use sammo\WebUtil;
use function sammo\addTurn;
use function sammo\cutTurn;
use function sammo\getGeneralSpecialWarName;
use function sammo\getRandTurn;
use function sammo\pushAdminLog;
use function sammo\resetInheritanceUser;
class Join extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v
->rule('required', [
'name',
'leadership',
'strength',
'intel',
'pic',
'character',
])
->rule('integer', [
'leadership',
'strength',
'intel',
'inheritTurntime',
])
->rule('boolean', [
'pic'
])
->rule('stringWidthBetween', 'name', 1, 18)
->rule('min', [
'leadership',
'strength',
'intel'
], GameConst::$defaultStatMin)
->rule('max', [
'leadership',
'strength',
'intel'
], GameConst::$defaultStatMax)
->rule('in', 'character', array_merge(GameConst::$availablePersonality, ['Random']))
->rule('in', 'inheritSpecial', GameConst::$availableSpecialWar)
->rule('min', 'inheritTurntime', 0)
->rule('in', 'inheritCity', array_keys(CityConst::all()))
->rule('integerArray', 'inheritBonusStat');
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$userID = $session->userID;
$name = $this->args['name'];
$name = htmlspecialchars($name);
$name = StringUtil::removeSpecialCharacter($name);
$name = WebUtil::htmlPurify($name);
$name = StringUtil::textStrip($name);
$pic = $this->args['pic'];
$character = $this->args['character'];
$leadership = $this->args['leadership'];
$strength = $this->args['strength'];
$intel = $this->args['intel'];
$inheritSpecial = $this->args['inheritSpecial'] ?? null;
$inheritTurntime = $this->args['inheritTurntime'] ?? null;
$inheritCity = $this->args['inheritCity'] ?? null;
$inheritBonusStat = $this->args['inheritBonusStat'] ?? null;
$rootDB = RootDB::db();
//회원 테이블에서 정보확인
$member = $rootDB->queryFirstRow('SELECT `no`, id, picture, grade, `name`, imgsvr FROM member WHERE no=%i', $userID);
if (!$member) {
return "잘못된 접근입니다!!!";
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['year', 'month', 'maxgeneral', 'scenario', 'show_img_level', 'turnterm', 'turntime', 'genius', 'npcmode']);
########## 동일 정보 존재여부 확인. ##########
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
$oldGeneral = $db->queryFirstField('SELECT `no` FROM general WHERE `owner`=%i', $userID);
$oldName = $db->queryFirstField('SELECT `no` FROM general WHERE `name`=%s', $name);
if ($oldGeneral) {
return "이미 등록하셨습니다!";
}
if ($oldName) {
return "이미 있는 장수입니다. 다른 이름으로 등록해 주세요!";
}
if ($gameStor->maxgeneral <= $gencount) {
return "더이상 등록할 수 없습니다!";
}
if ($name == '') {
return "이름이 짧습니다. 다시 가입해주세요!";
}
if (mb_strwidth($name) > 18) {
return "이름이 유효하지 않습니다. 다시 가입해주세요!";
}
if ($leadership + $strength + $intel > GameConst::$defaultStatTotal) {
return "능력치가 " . GameConst::$defaultStatTotal . "을 넘어섰습니다. 다시 가입해주세요!";
}
if ($inheritBonusStat) {
if (count($inheritBonusStat) != 3) {
return "보너스 능력치가 잘못 지정되었습니다. 다시 가입해주세요!";
}
foreach ($inheritBonusStat as $stat) {
if ($stat < 0) {
return "보너스 능력치가 음수입니다. 다시 가입해주세요!";
}
}
$sum = array_sum($inheritBonusStat);
if ($sum == 0) {
$inheritBonusStat = null;
} else if ($sum < 3 || $sum > 5) {
return "보너스 능력치 합이 잘못 지정되었습니다. 다시 가입해주세요!";
}
}
$admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year', 'month']);
$inheritTotalPoint = resetInheritanceUser($userID);
$inheritRequiredPoint = 0;
$userLogger = new UserLogger($userID, $admin['year'], $admin['month'], false);
if ($inheritCity !== null) {
$inheritRequiredPoint += GameConst::$inheritBornCityPoint;
}
if ($inheritBonusStat !== null) {
$inheritRequiredPoint += GameConst::$inheritBornStatPoint;
}
if ($inheritSpecial !== null) {
$inheritRequiredPoint += GameConst::$inheritBornSpecialPoint;
}
if ($inheritTurntime !== null) {
$inheritRequiredPoint += GameConst::$inheritBornTurntimePoint;
}
if ($inheritTotalPoint < $inheritRequiredPoint) {
return "유산 포인트가 부족합니다. 다시 가입해주세요!";
}
if ($inheritSpecial !== null && $gameStor->genius == 0) {
return "이미 천재가 모두 나타났습니다. 다시 가입해주세요!";
}
if ($inheritCity !== null && !key_exists($inheritCity, CityConst::all())) {
return "도시가 잘못 지정되었습니다. 다시 가입해주세요!";
}
if ($inheritSpecial) {
$speicalText = getGeneralSpecialWarName($inheritSpecial);
$userLogger->push("{$speicalText} 전투 특기를 가진 천재 생성", "inheritPoint");
$genius = true;
} else {
// 현재 1%
$genius = Util::randBool(0.01);
}
if ($genius && $gameStor->genius > 0) {
$gameStor->genius = $gameStor->genius - 1;
} else {
$genius = false;
}
if ($inheritCity !== null) {
$cityname = CityConst::byID($inheritCity)->name;
$userLogger->push("{$cityname}에 장수 생성", "inheritPoint");
$city = $inheritCity;
} else {
// 공백지에서만 태어나게
$city = $db->queryFirstField("select city from city where level>=5 and level<=6 and nation=0 order by rand() limit 0,1");
if (!$city) {
$city = $db->queryFirstField("select city from city where level>=5 and level<=6 order by rand() limit 0,1");
}
}
if ($inheritBonusStat) {
[$pleadership, $pstrength, $pintel] = $inheritBonusStat;
$userLogger->push("{$pleadership}, {$pstrength}, {$pintel} 보너스 능력치로 생성", "inheritPoint");
} else {
$pleadership = 0;
$pstrength = 0;
$pintel = 0;
foreach (Util::range(Util::randRangeInt(3, 5)) as $statIdx) {
switch (Util::choiceRandomUsingWeight([$leadership, $strength, $intel])) {
case 0:
$pleadership++;
break;
case 1:
$pstrength++;
break;
case 2:
$pintel++;
break;
}
}
}
$leadership = $leadership + $pleadership;
$strength = $strength + $pstrength;
$intel = $intel + $pintel;
$relYear = Util::valueFit($admin['year'] - $admin['startyear'], 0);
$age = 20 + ($pleadership + $pstrength + $pintel) * 2 - (mt_rand(0, 1));
// 아직 남았고 천재등록상태이면 특기 부여
if ($genius) {
$specage2 = $age;
if ($inheritSpecial) {
$special2 = $inheritSpecial;
} else {
$special2 = SpecialityHelper::pickSpecialWar([
'leadership' => $leadership,
'strength' => $strength,
'intel' => $intel,
'dex1' => 0,
'dex2' => 0,
'dex3' => 0,
'dex4' => 0,
'dex5' => 0
]);
}
} else {
$specage2 = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 6 - $relYear / 2), 3) + $age;
$special2 = GameConst::$defaultSpecialWar;
}
//내특
$specage = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 12 - $relYear / 2), 3) + $age;
$special = GameConst::$defaultSpecialDomestic;
if ($admin['scenario'] >= 1000) {
$specage2 = $age + 3;
$specage = $age + 3;
}
if ($relYear < 3) {
$experience = 0;
} else {
$expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 4');
$targetGenOrder = Util::round($expGenCount * 0.2);
$experience = $db->queryFirstField(
'SELECT experience FROM general WHERE nation != 0 AND npc < 4 ORDER BY experience ASC LIMIT %i, 1',
$targetGenOrder - 1
);
$experience *= 0.8;
}
if ($inheritTurntime !== null) {
$inheritTurntime = $inheritTurntime % ($admin['turnterm'] * 60);
$userLogger->push(sprintf("턴 시간 %02d:%02d 로 지정", intdiv($inheritTurntime, 60), $inheritTurntime%60), "inheritPoint");
$inheritTurntime += Util::randRangeInt(0, 999999) / 1000000;
$turntime = new \DateTimeImmutable(cutTurn($admin['turntime'], $admin['turnterm']));
$turntime = $turntime->add(TimeUtil::secondsToDateInterval($inheritTurntime));
$turntime = TimeUtil::format($turntime, true);
} else {
$turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime']));
}
$now = TimeUtil::now(true);
if ($now >= $turntime) {
$turntime = addTurn($turntime, $admin['turnterm']);
}
//특회 전콘
if ($admin['show_img_level'] >= 1 && $member['grade'] >= 1 && $member['picture'] != "" && $pic) {
$face = $member['picture'];
$imgsvr = $member['imgsvr'];
} else {
$face = "default.jpg";
$imgsvr = 0;
}
//성격 랜덤시
if (!in_array($character, GameConst::$availablePersonality)) {
$character = Util::choiceRandom(GameConst::$availablePersonality);
}
//상성 랜덤
$affinity = rand() % 150 + 1;
########## 회원정보 테이블에 입력값을 등록한다. ##########
$db->insert('general', [
'owner' => $userID,
'name' => $name,
'owner_name' => $member['name'],
'picture' => $face,
'imgsvr' => $imgsvr,
'nation' => 0,
'city' => $city,
'troop' => 0,
'affinity' => $affinity,
'leadership' => $leadership,
'strength' => $strength,
'intel' => $intel,
'experience' => $experience,
'dedication' => 0,
'gold' => GameConst::$defaultGold,
'rice' => GameConst::$defaultRice,
'crew' => 0,
'train' => 0,
'atmos' => 0,
'officer_level' => 0,
'turntime' => $turntime,
'killturn' => 6,
'lastconnect' => $now,
'lastrefresh' => $now,
'crewtype' => GameUnitConst::DEFAULT_CREWTYPE,
'makelimit' => 0,
'age' => $age,
'startage' => $age,
'personal' => $character,
'specage' => $specage,
'special' => $special,
'specage2' => $specage2,
'special2' => $special2
]);
$generalID = $db->insertId();
$turnRows = [];
foreach (Util::range(GameConst::$maxTurn) as $turnIdx) {
$turnRows[] = [
'general_id' => $generalID,
'turn_idx' => $turnIdx,
'action' => '휴식',
'arg' => null,
'brief' => '휴식'
];
}
$db->insert('general_turn', $turnRows);
$rank_data = [];
foreach (array_keys(General::RANK_COLUMN) as $rankColumn) {
$rank_data[] = [
'general_id' => $generalID,
'nation_id' => 0,
'type' => $rankColumn,
'value' => 0
];
}
$db->insert('rank_data', $rank_data);
$db->insert('betting', [
'general_id' => $generalID,
]);
$cityname = CityConst::byID($city)->name;
if ($inheritRequiredPoint > 0) {
$userLogger->push("장수 생성으로 포인트 {$inheritRequiredPoint} 소모", "inheritPoint");
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}");
$inheritStor->setValue('previous', [$inheritTotalPoint - $inheritRequiredPoint, null]);
$userLogger->flush();
}
$me = [
'no' => $generalID
];
$log = [];
$mylog = [];
$logger = new ActionLogger($generalID, 0, $gameStor->year, $gameStor->month);
$josaRa = JosaUtil::pick($name, '라');
$speicalText = getGeneralSpecialWarName($special2);
if ($genius) {
$logger->pushGlobalActionLog("<G><b>{$cityname}</b></>에서 <Y>{$name}</>{$josaRa}는 기재가 천하에 이름을 알립니다.");
$logger->pushGlobalActionLog("<C>{$speicalText}</> 특기를 가진 <C>천재</>의 등장으로 온 천하가 떠들썩합니다.");
$logger->pushGlobalHistoryLog("<L><b>【천재】</b></><G><b>{$cityname}</b></>에 천재가 등장했습니다.");
} else {
$logger->pushGlobalActionLog("<G><b>{$cityname}</b></>에서 <Y>{$name}</>{$josaRa}는 호걸이 천하에 이름을 알립니다.");
}
$logger->pushGeneralHistoryLog("<Y>{$name}</>, <G>{$cityname}</>에서 큰 뜻을 품다.");
$logger->pushGeneralActionLog("삼국지 모의전투 PHP의 세계에 오신 것을 환영합니다 ^o^", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("처음 하시는 경우에는 <D>도움말</>을 참고하시고,", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("문의사항이 있으시면 게시판에 글을 남겨주시면 되겠네요~", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("부디 즐거운 삼모전 되시길 바랍니다 ^^", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("통솔 <C>$pleadership</> 무력 <C>$pstrength</> 지력 <C>$pintel</> 의 보너스를 받으셨습니다.", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("연령은 <C>$age</>세로 시작합니다.", ActionLogger::PLAIN);
if ($genius) {
$logger->pushGeneralActionLog("축하합니다! 천재로 태어나 처음부터 <C>{$speicalText}</> 특기를 가지게 됩니다!", ActionLogger::PLAIN);
$logger->pushGeneralHistoryLog("<C>{$speicalText}</> 특기를 가진 천재로 탄생.");
}
$logger->flush();
pushAdminLog(["가입 : {$userID} // {$name} // {$generalID}" . getenv("REMOTE_ADDR")]);
$rootDB->insert('member_log', [
'member_no' => $userID,
'date' => TimeUtil::now(),
'action_type' => 'make_general',
'action' => Json::encode([
'server' => DB::prefix(),
'type' => 'general',
'generalID' => $generalID,
'generalName' => $name
])
]);
return null;
}
}
@@ -0,0 +1,86 @@
<?php
namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\GameConst;
use sammo\General;
use sammo\KVStorage;
use sammo\TimeUtil;
use sammo\TriggerInheritBuff;
use sammo\UserLogger;
use sammo\Validator;
class BuyHiddenBuff extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('required', [
'type',
'level',
])
->rule('integer', 'level')
->rule('min', 'level', 1)
->rule('max', 'level', TriggerInheritBuff::MAX_STEP)
->rule('keyExists', 'type', TriggerInheritBuff::BUFF_KEY_TEXT);
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
//General.aux 쓰므로 lock;
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$userID = $session->userID;
$generalID = $session->generalID;
$type = $this->args['type'];
$level = $this->args['level'];
$general = General::createGeneralObjFromDB($generalID);
if ($userID != $general->getVar('owner')) {
return '로그인 상태가 이상합니다. 다시 로그인해 주세요.';
}
$userLogger = new UserLogger($userID);
$inheritBuffList = $general->getAuxVar('inheritBuff') ?? [];
$prevLevel = $inheritBuffList[$type] ?? 0;
if ($prevLevel == $level) {
return '이미 구입했습니다.';
}
if ($prevLevel > $level) {
return '이미 더 높은 등급을 구입했습니다.';
}
$reqAmount = GameConst::$inheritBuffPoints[$level] - GameConst::$inheritBuffPoints[$prevLevel];
$db = DB::db();
$inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}");
$previousPoint = ($inheritStor->getValue('previous') ?? [0,0])[0];
if ($previousPoint < $reqAmount) {
return '충분한 유산 포인트를 가지고 있지 않습니다.';
}
$buffTypeText = TriggerInheritBuff::BUFF_KEY_TEXT[$type];
$moreText = $prevLevel > 0 ? "추가":"";
$userLogger->push("{$reqAmount} 포인트로 {$buffTypeText} {$level} 단계 {$moreText}구입", "inheritPoint");
$userLogger->flush();
$inheritBuffList[$type] = $level;
$general->setAuxVar('inheritBuff', $inheritBuffList);
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
$general->applyDB($db);
return null;
}
}
@@ -0,0 +1,58 @@
<?php
namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\GameConst;
use sammo\General;
use sammo\KVStorage;
use sammo\TimeUtil;
use sammo\UserLogger;
class BuyRandomUnique extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
return null;
}
public function getRequiredSessionMode(): int
{
//General.aux 쓰므로 lock;
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$userID = $session->userID;
$generalID = $session->generalID;
$general = General::createGeneralObjFromDB($generalID);
if($userID != $general->getVar('owner')){
return '로그인 상태가 이상합니다. 다시 로그인해 주세요.';
}
if($general->getAuxVar('inheritRandomUnique') !== null){
return '이미 구입 명령을 내렸습니다. 다음 턴까지 기다려주세요.';
}
$db = DB::db();
$inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}");
$previousPoint = ($inheritStor->getValue('previous')??[0, 0])[0];
$reqAmount = GameConst::$inheritItemRandomPoint;
if($previousPoint < $reqAmount){
return '충분한 유산 포인트를 가지고 있지 않습니다.';
}
$userLogger = new UserLogger($userID);
$userLogger->push("{$reqAmount} 포인트로 랜덤 유니크 구입", "inheritPoint");
$userLogger->flush();
$general->setAuxVar('inheritRandomUnique', TimeUtil::now());
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
$general->applyDB($db);
return null;
}
}
@@ -0,0 +1,88 @@
<?php
namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\GameConst;
use sammo\General;
use sammo\KVStorage;
use sammo\UserLogger;
use sammo\Validator;
use function sammo\buildItemClass;
class BuySpecificUnique extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
foreach (GameConst::$allItems as $items) {
foreach ($items as $itemKey => $amount) {
if ($amount == 0) {
continue;
}
$availableItems[$itemKey] = $amount;
}
}
$v = new Validator($this->args);
$v->rule('required', [
'item',
'amount',
])
->rule('integer', 'amount')
->rule('min', 'amount', GameConst::$inheritItemUniqueMinPoint)
->rule('keyExists', 'item', $availableItems);
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
//KVStrorage, General.aux 모두 쓰므로 lock;
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$itemKey = $this->args['item'];
$amount = $this->args['amount'];
$userID = $session->userID;
$generalID = $session->generalID;
$general = General::createGeneralObjFromDB($generalID);
if ($userID != $general->getVar('owner')) {
return '로그인 상태가 이상합니다. 다시 로그인해 주세요.';
}
$itemTrials = $general->getAuxVar('inheritUniqueTrial') ?? [];
if (key_exists($itemKey, $itemTrials)) {
return '이미 입찰한 아이템입니다. 다음 턴에 시도해 주세요.';
}
$db = DB::db();
$inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}");
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}");
$previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0];
if ($previousPoint < $amount) {
return '충분한 유산 포인트를 가지고 있지 않습니다.';
}
$itemObj = buildItemClass($itemKey);
$userLogger = new UserLogger($userID);
$userLogger->push("{$amount} 포인트로 유니크 {$itemObj->getName()} 구입 시도", "inheritPoint");
$userLogger->flush();
$itemTrials[$itemKey] = $amount;
$general->setAuxVar('inheritUniqueTrial', $itemTrials);
$inheritStor->setValue('previous', [$previousPoint - $amount, null]);
$trialStor->setValue("u{$userID}", [$userID, $generalID, $amount]);
$general->applyDB($db);
return null;
}
}
@@ -0,0 +1,74 @@
<?php
namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\GameConst;
use sammo\General;
use sammo\KVStorage;
use sammo\UserLogger;
use sammo\Validator;
class ResetSpecialWar extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
return null;
}
public function getRequiredSessionMode(): int
{
//KVStrorage, General.aux 모두 쓰므로 lock;
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$userID = $session->userID;
$generalID = $session->generalID;
$general = General::createGeneralObjFromDB($generalID);
if ($userID != $general->getVar('owner')) {
return '로그인 상태가 이상합니다. 다시 로그인해 주세요.';
}
$currentSpecialWar = $general->getVar('special2');
if ($currentSpecialWar === null || $currentSpecialWar == 'None') {
return '이미 전투 특기가 공란입니다.';
}
$currentLevel = $general->getAuxVar('inheritResetSpecialWar') ?? -1;
$nextLevel = $currentLevel + 1;
while (count(GameConst::$inheritResetAttrPointBase) <= $nextLevel) {
$baseLen = count(GameConst::$inheritResetAttrPointBase);
GameConst::$inheritResetAttrPointBase[] = GameConst::$inheritResetAttrPointBase[$baseLen - 1] + GameConst::$inheritResetAttrPointBase[$baseLen - 2];
}
$reqPoint = GameConst::$inheritResetAttrPointBase[$nextLevel];
$db = DB::db();
$inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}");
$previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0];
if ($previousPoint < $reqPoint) {
return '충분한 유산 포인트를 가지고 있지 않습니다.';
}
$userLogger = new UserLogger($userID);
$userLogger->push("{$reqPoint} 포인트로 전투 특기 초기화", "inheritPoint");
$userLogger->flush();
$oldTypeKey = 'prev_types_special2';
$oldSpecialList = $general->getAuxVar($oldTypeKey) ?? [];
$oldSpecialList[] = $currentSpecialWar;
$general->setAuxVar($oldTypeKey, $oldSpecialList);
$general->setAuxVar('inheritResetSpecialWar', $nextLevel);
$general->setVar('special2', 'None');
$inheritStor->setValue('previous', [$previousPoint - $reqPoint, null]);
$general->applyDB($db);
return null;
}
}
@@ -0,0 +1,83 @@
<?php
namespace sammo\API\InheritAction;
use DateTimeImmutable;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\GameConst;
use sammo\General;
use sammo\KVStorage;
use sammo\TimeUtil;
use sammo\UserLogger;
use sammo\Util;
class ResetTurnTime extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
return null;
}
public function getRequiredSessionMode(): int
{
//KVStrorage, General.aux 모두 쓰므로 lock;
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$userID = $session->userID;
$generalID = $session->generalID;
$general = General::createGeneralObjFromDB($generalID);
if ($userID != $general->getVar('owner')) {
return '로그인 상태가 이상합니다. 다시 로그인해 주세요.';
}
$currentLevel = $general->getAuxVar('inheritResetTurnTime') ?? -1;
$nextLevel = $currentLevel + 1;
while (count(GameConst::$inheritResetAttrPointBase) <= $nextLevel) {
$baseLen = count(GameConst::$inheritResetAttrPointBase);
GameConst::$inheritResetAttrPointBase[] = GameConst::$inheritResetAttrPointBase[$baseLen - 1] + GameConst::$inheritResetAttrPointBase[$baseLen - 2];
}
$reqPoint = GameConst::$inheritResetAttrPointBase[$nextLevel];
$db = DB::db();
$inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}");
$previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0];
if ($previousPoint < $reqPoint) {
return '충분한 유산 포인트를 가지고 있지 않습니다.';
}
$gameStor = new KVStorage($db, 'game_env');
[$turnTerm, $serverTurnTime] = $gameStor->getValuesAsArray(['turnterm', 'turntime']);
$currTurnTime = new DateTimeImmutable($general->getTurnTime());
$serverTurnTimeObj = new DateTimeImmutable($serverTurnTime);
$afterTurn = Util::randRange($turnTerm * -60 / 2, $turnTerm * 60 / 2);
$userLogger = new UserLogger($userID);
if($afterTurn >= 0){
$userLogger->push(sprintf("{$reqPoint} 포인트로 턴 시간을 바꾼 결과 %02d:%02d 뒤로 밀림", intdiv($afterTurn, 60), $afterTurn%60), "inheritPoint");
}
else{
$userLogger->push(sprintf("{$reqPoint} 포인트로 턴 시간을 바꾼 결과 %02d:%02d 앞으로 당김", intdiv(-$afterTurn, 60), (-$afterTurn)%60), "inheritPoint");
}
$userLogger->flush();
$turnTime = $currTurnTime->add(TimeUtil::secondsToDateInterval($afterTurn));
if ($turnTime <= $serverTurnTimeObj && $serverTurnTimeObj <= $currTurnTime) {
$turnTime = $turnTime->add(TimeUtil::secondsToDateInterval($turnTerm * 60));
}
$general->setVar('turntime', TimeUtil::format($turnTime, true));
$general->setAuxVar('inheritResetTurnTime', $nextLevel);
$inheritStor->setValue('previous', [$previousPoint - $reqPoint, null]);
$general->applyDB($db);
return null;
}
}
@@ -0,0 +1,83 @@
<?php
namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\GameConst;
use sammo\General;
use sammo\KVStorage;
use sammo\UserLogger;
use sammo\Validator;
use function sammo\buildGeneralSpecialWarClass;
class SetNextSpecialWar extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('required', [
'type',
])
->rule('in', 'type', GameConst::$availableSpecialWar);
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
//General.aux 쓰므로 lock;
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$userID = $session->userID;
$generalID = $session->generalID;
$type = $this->args['type'];
$general = General::createGeneralObjFromDB($generalID);
if ($userID != $general->getVar('owner')) {
return '로그인 상태가 이상합니다. 다시 로그인해 주세요.';
}
$inheritSpecificSpecialWar = $general->getAuxVar('inheritSpecificSpecialWar');
$currentSpecialWar = $general->getVar('special2');
if ($currentSpecialWar == $type) {
return '이미 그 특기를 보유하고 있습니다.';
}
if ($inheritSpecificSpecialWar == $type) {
return '이미 그 특기를 예약하였습니다.';
}
if ($inheritSpecificSpecialWar !== null) {
return '이미 예약한 특기가 있습니다.';
}
$reqAmount = GameConst::$inheritSpecificSpecialPoint;
$db = DB::db();
$inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}");
$previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0];
if ($previousPoint < $reqAmount) {
return '충분한 유산 포인트를 가지고 있지 않습니다.';
}
$userLogger = new UserLogger($userID);
$specialWarObj = buildGeneralSpecialWarClass($type);
$userLogger->push("{$reqAmount} 포인트로 다음 전투 특기로 {$specialWarObj->getName()} 지정", "inheritPoint");
$userLogger->flush();
$general->setAuxVar('inheritSpecificSpecialWar', $type);
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
$general->applyDB($db);
return null;
}
}
@@ -19,7 +19,7 @@ class che_무기_09_동호비궁 extends \sammo\BaseStatItem{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 109, 0.15, 20, 40),
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 109, 0.2, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
@@ -19,7 +19,7 @@ class che_무기_13_양유기궁 extends \sammo\BaseStatItem{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 113, 0.05, 20, 40),
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 113, 0.1, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
@@ -19,9 +19,16 @@ class che_반계_백우선 extends \sammo\BaseItem{
protected $cost = 200;
protected $consumable = false;
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
$debuff = [
'warMagicSuccessProb' => 0.1,
][$statName] ?? 0;
return $value - $debuff;
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*301, false, '계략약화'),
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*301),
new che_반계발동($unit)
);
@@ -19,9 +19,16 @@ class che_반계_파초선 extends \sammo\BaseItem{
protected $cost = 200;
protected $consumable = false;
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
$debuff = [
'warMagicSuccessProb' => 0.1,
][$statName] ?? 0;
return $value - $debuff;
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*302, false, '계략약화'),
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*302),
new che_반계발동($unit)
);
@@ -18,9 +18,11 @@ class che_서적_07_논어 extends \sammo\BaseStatItem{
$this->info .= "<br>[전투] 상대의 계략 성공 확률 -10%p";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*207, false, '계략약화')
);
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
$debuff = [
'warMagicSuccessProb' => 0.1,
][$statName] ?? 0;
return $value - $debuff;
}
}
@@ -18,9 +18,11 @@ class che_서적_11_춘추전 extends \sammo\BaseStatItem{
$this->info .= "<br>[전투] 상대의 계략 성공 확률 -10%p";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*211, false, '계략약화')
);
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
$debuff = [
'warMagicSuccessProb' => 0.1,
][$statName] ?? 0;
return $value - $debuff;
}
}
@@ -1,5 +1,7 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\GeneralTrigger;
@@ -17,7 +19,8 @@ use sammo\WarUnitTrigger\che_전멸시페이즈증가;
use sammo\WarUnitTrigger\che_부상무효;
use sammo\WarUnitTrigger\WarActivateSkills;
class che_치트_HideD의_사인검 extends \sammo\BaseItem{
class che_치트_HideD의_사인검 extends \sammo\BaseItem
{
protected $rawName = 'HideD의 사인검';
protected $name = 'HideD의 사인검(치트)';
@@ -37,33 +40,45 @@ EOT;
protected $consumable = false;
protected $buyable = false;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if($turnType == '계략'){
if($varType == 'success') return $value + 2;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux = null): float
{
if ($turnType == '계략') {
if ($varType == 'success') return $value + 2;
}
return $value;
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
public function onCalcStat(General $general, string $statName, $value, $aux = null)
{
$bonus = [
'bonusTrain'=>30,
'bonusAtmos'=>30,
'leadership'=>100,
'strength'=>100,
'intel'=>100,
'warMagicSuccessProb'=>1,
][$statName]??0;
'bonusTrain' => 30,
'bonusAtmos' => 30,
'leadership' => 100,
'strength' => 100,
'intel' => 100,
'warMagicSuccessProb' => 1,
][$statName] ?? 0;
return $bonus + $value;
}
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
$debuff = [
'warMagicSuccessProb' => 0.1,
][$statName] ?? 0;
return $value - $debuff;
}
public function getPreTurnExecuteTriggerList(General $general): ?GeneralTriggerCaller
{
return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general)
);
}
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
new che_부상무효($unit, BaseWarUnitTrigger::TYPE_NONE),
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가')
@@ -73,10 +88,10 @@ EOT;
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '필살불가', '위압불가', '격노불가', '계략약화', '저격불가'),
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '필살불가', '위압불가', '격노불가', '저격불가'),
new che_전투치료시도($unit),
new che_전투치료발동($unit),
new che_저격시도($unit, che_저격시도::TYPE_NONE, 1/2, 20, 60),
new che_저격시도($unit, che_저격시도::TYPE_NONE, 1 / 2, 20, 60),
new che_저격발동($unit),
new che_격노시도($unit),
new che_격노발동($unit),
@@ -84,8 +99,8 @@ EOT;
);
}
public function getWarPowerMultiplier(WarUnit $unit):array{
public function getWarPowerMultiplier(WarUnit $unit): array
{
return [1, 0.95];
}
}
}
@@ -28,10 +28,17 @@ class event_전투특기_반계 extends \sammo\BaseItem{
return $value;
}
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
$debuff = [
'warMagicSuccessProb' => 0.1,
][$statName] ?? 0;
return $value - $debuff;
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*401, false, '계략약화'),
new che_반계시도($unit),
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
new che_반계발동($unit)
);
}
@@ -21,6 +21,14 @@ class che_event_견고 extends \sammo\BaseSpecial{
SpecialityHelper::STAT_STRENGTH
];
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
$debuff = [
'warMagicSuccessProb' => 0.1,
][$statName] ?? 0;
return $value - $debuff;
}
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_부상무효($unit, BaseWarUnitTrigger::TYPE_ITEM),
@@ -30,7 +38,7 @@ class che_event_견고 extends \sammo\BaseSpecial{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*402, false, '필살불가', '계략약화', '저격불가')
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*402, false, '필살불가', '저격불가')
);
}
@@ -33,10 +33,17 @@ class che_event_반계 extends \sammo\BaseSpecial
return $value;
}
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
$debuff = [
'warMagicSuccessProb' => 0.1,
][$statName] ?? 0;
return $value - $debuff;
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE * 403, false, '계략약화'),
new che_반계시도($unit),
new che_반계발동($unit)
);
+9 -1
View File
@@ -24,6 +24,14 @@ class che_견고 extends \sammo\BaseSpecial
SpecialityHelper::STAT_STRENGTH
];
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
$debuff = [
'warMagicSuccessProb' => 0.1,
][$statName] ?? 0;
return $value - $debuff;
}
public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
@@ -35,7 +43,7 @@ class che_견고 extends \sammo\BaseSpecial
public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE * 404, false, '필살불가', '계략약화', '저격불가')
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE * 404, false, '필살불가', '저격불가')
);
}
+8 -1
View File
@@ -29,9 +29,16 @@ class che_반계 extends \sammo\BaseSpecial{
return $value;
}
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
$debuff = [
'warMagicSuccessProb' => 0.1,
][$statName] ?? 0;
return $value - $debuff;
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM + BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE * 406, false, '계략약화'),
new che_반계시도($unit),
new che_반계발동($unit)
);
+28
View File
@@ -0,0 +1,28 @@
<?php
namespace sammo;
abstract class BaseAPI
{
const NO_SESSION = 0;
const REQ_LOGIN = 1;
const REQ_GAME_LOGIN = 2;
const REQ_READ_ONLY = 4;
protected array $args;
protected string $rootPath;
public function __construct(string $rootPath, array $args)
{
$this->rootPath = $rootPath;
$this->args = $args;
}
abstract public function getRequiredSessionMode(): int;
abstract function validateArgs(): ?string;
/** @return null|string|array */
abstract function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag);
public function tryCache():?string{
return null;
}
}
+6 -5
View File
@@ -4,7 +4,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
CityConst,
CityConst,
ActionLogger,
LastTurn,
Command
@@ -13,6 +13,7 @@ use \sammo\{
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use function sammo\tryRollbackInheritUniqueItem;
class che_NPC능동 extends Command\GeneralCommand{
static protected $actionName = 'NPC능동';
@@ -46,7 +47,7 @@ class che_NPC능동 extends Command\GeneralCommand{
$general = $this->generalObj;
$this->setNation();
$this->permissionConstraints=[
ConstraintHelper::MustBeNPC()
@@ -65,7 +66,7 @@ class che_NPC능동 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -97,11 +98,11 @@ class che_NPC능동 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
}
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
return true;
}
}
+3
View File
@@ -13,6 +13,7 @@ use \sammo\LastTurn;
use \sammo\Command;
use function \sammo\printCitiesBasedOnDistance;
use function sammo\tryUniqueItemLottery;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
@@ -161,6 +162,8 @@ class che_강행 extends Command\GeneralCommand
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
return true;
+20 -19
View File
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -16,13 +16,12 @@ use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst;
use function sammo\refreshNationStaticInfo;
use function sammo\getAllNationStaticInfo;
use function sammo\tryUniqueItemLottery;
class che_거병 extends Command\GeneralCommand{
static protected $actionName = '거병';
protected function argTest():bool{
protected function argTest():bool{
$this->arg = [];
return true;
@@ -38,7 +37,7 @@ class che_거병 extends Command\GeneralCommand{
$this->setNation();
$relYear = $env['year'] - $env['startyear'];
$this->fullConditionConstraints=[
ConstraintHelper::BeNeutral(),
ConstraintHelper::BeOpeningPart($relYear+1),
@@ -49,7 +48,7 @@ class che_거병 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -93,15 +92,15 @@ class che_거병 extends Command\GeneralCommand{
DB::db()->insert('nation', [
'name'=>$nationName,
'color'=>'#330000',
'gold'=>0,
'rice'=>GameConst::$baserice,
'rate'=>20,
'bill'=>100,
'strategic_cmd_limit'=>12,
'surlimit'=>72,
'color'=>'#330000',
'gold'=>0,
'rice'=>GameConst::$baserice,
'rate'=>20,
'bill'=>100,
'strategic_cmd_limit'=>12,
'surlimit'=>72,
'secretlimit'=>$secretlimit,
'type'=>GameConst::$neutralNationType,
'type'=>GameConst::$neutralNationType,
'gennum'=>1
]);
$nationID = DB::db()->insertId();
@@ -114,7 +113,7 @@ class che_거병 extends Command\GeneralCommand{
if($nationID == $destNationID){
continue;
}
$diplomacyInit[] = [
'me'=>$destNationID,
'you'=>$nationID,
@@ -132,9 +131,9 @@ class che_거병 extends Command\GeneralCommand{
if($diplomacyInit){
$db->insert('diplomacy', $diplomacyInit);
}
$turnRows = [];
foreach([12, 11] as $chiefLevel){
foreach(Util::range(GameConst::$maxChiefTurn) as $turnIdx){
@@ -147,7 +146,7 @@ class che_거병 extends Command\GeneralCommand{
'brief'=>'휴식',
];
}
}
$db->insert('nation_turn', $turnRows);
@@ -172,10 +171,12 @@ class che_거병 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
return true;
}
}
+7 -4
View File
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -14,10 +14,11 @@ use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use \sammo\TextDecoration\SightseeingMessage;
use function sammo\tryUniqueItemLottery;
class che_견문 extends Command\GeneralCommand{
static protected $actionName = '견문';
protected function argTest():bool{
$this->arg = null;
return true;
@@ -41,7 +42,7 @@ class che_견문 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -111,10 +112,12 @@ class che_견문 extends Command\GeneralCommand{
$general->addExperience($exp);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
return true;
}
}
+12 -8
View File
@@ -5,7 +5,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -16,6 +16,8 @@ use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use sammo\MustNotBeReachedException;
use function sammo\tryUniqueItemLottery;
class che_군량매매 extends Command\GeneralCommand{
static protected $actionName = '군량매매';
static public $reqArg = true;
@@ -57,7 +59,7 @@ class che_군량매매 extends Command\GeneralCommand{
$general = $this->generalObj;
$this->setCity();
$this->setNation();
$this->setNation();
$this->minConditionConstraints=[
ConstraintHelper::ReqCityTrader($general->getNPCType()),
@@ -69,7 +71,7 @@ class che_군량매매 extends Command\GeneralCommand{
protected function initWithArg()
{
$general = $this->generalObj;
$this->fullConditionConstraints=[
ConstraintHelper::ReqCityTrader($general->getNPCType()),
ConstraintHelper::OccupiedCity(true),
@@ -87,7 +89,7 @@ class che_군량매매 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -120,7 +122,7 @@ class che_군량매매 extends Command\GeneralCommand{
else{
$tradeRate /= 100;
}
if($buyRice){
$buyKey = 'rice';
$sellKey = 'gold';
@@ -153,7 +155,7 @@ class che_군량매매 extends Command\GeneralCommand{
else{
$logger->pushGeneralActionLog("군량 <C>{$sellAmountText}</>을 팔아 자금 <C>{$buyAmountText}</>을 얻었습니다. <1>$date</>");
}
$general->increaseVar($buyKey, $buyAmount);
$general->increaseVarWithLimit($sellKey, -$sellAmount, 0);
@@ -163,7 +165,7 @@ class che_군량매매 extends Command\GeneralCommand{
$exp = 30;
$ded = 50;
$incStat = Util::choiceRandomUsingWeight([
'leadership_exp'=>$general->getLeadership(false, false, false, false),
'strength_exp'=>$general->getStrength(false, false, false, false),
@@ -176,6 +178,8 @@ class che_군량매매 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
return true;
@@ -199,5 +203,5 @@ class che_군량매매 extends Command\GeneralCommand{
return ob_get_clean();
}
}
+8 -6
View File
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -14,7 +14,7 @@ use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst;
use function sammo\tryUniqueItemLottery;
class che_귀환 extends Command\GeneralCommand{
static protected $actionName = '귀환';
@@ -33,7 +33,7 @@ class che_귀환 extends Command\GeneralCommand{
$this->setNation();
[$reqGold, $reqRice] = $this->getCost();
$this->fullConditionConstraints=[
ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
@@ -49,7 +49,7 @@ class che_귀환 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -87,7 +87,7 @@ class che_귀환 extends Command\GeneralCommand{
$exp = 70;
$ded = 100;
$general->setVar('city', $destCityID);
$general->addExperience($exp);
@@ -95,10 +95,12 @@ class che_귀환 extends Command\GeneralCommand{
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
return true;
}
}
+7 -4
View File
@@ -15,6 +15,7 @@ use \sammo\{
use function \sammo\getAllNationStaticInfo;
use function \sammo\getNationStaticInfo;
use function \sammo\newColor;
use function sammo\tryUniqueItemLottery;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
@@ -64,7 +65,7 @@ class che_등용 extends Command\GeneralCommand{
$this->minConditionConstraints=[
ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'),
ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotBeNeutral(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::SuppliedCity(),
];
@@ -80,7 +81,7 @@ class che_등용 extends Command\GeneralCommand{
$this->fullConditionConstraints=[
ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'),
ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotBeNeutral(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::SuppliedCity(),
ConstraintHelper::ExistsDestGeneral(),
@@ -110,7 +111,7 @@ class che_등용 extends Command\GeneralCommand{
) * 10;
return [$reqGold, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -141,7 +142,7 @@ class che_등용 extends Command\GeneralCommand{
$destGeneralName = $this->destGeneralObj->getName();
$destGeneralID = $this->destGeneralObj->getID();
$msg = ScoutMessage::buildScoutMessage($general->getID(), $destGeneralID, $reason, new \DateTime($general->getTurnTime()));
if($msg){
@@ -164,6 +165,8 @@ class che_등용 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
return true;
@@ -36,7 +36,7 @@ class che_랜덤임관 extends Command\GeneralCommand
/*if($this->arg === null){
return true;
}
$destNationIDList = $this->arg['destNationIDList']??null;
//null은 에러, []는 정상
@@ -56,8 +56,8 @@ class che_랜덤임관 extends Command\GeneralCommand
}
$this->arg = [
'destNationIDList' => $destNationIDList
];
];
return true;*/
}
@@ -234,7 +234,7 @@ class che_랜덤임관 extends Command\GeneralCommand
if (!$destNation) {
//임관 가능한 국가가 없다!
$logger->pushGeneralActionLog("임관 가능한 국가가 없습니다. <1>$date</>");
$this->alternative = new che_요양($general, $this->env, null);
$this->alternative = new che_인재탐색($general, $this->env, null);
return false;
}
@@ -14,6 +14,8 @@ use \sammo\{
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use function sammo\tryRollbackInheritUniqueItem;
class che_모반시도 extends Command\GeneralCommand{
static protected $actionName = '모반시도';
@@ -29,7 +31,7 @@ class che_모반시도 extends Command\GeneralCommand{
$this->setCity();
$this->setNation();
$this->fullConditionConstraints=[
ConstraintHelper::NotBeNeutral(),
ConstraintHelper::BeChief(),
@@ -43,7 +45,7 @@ class che_모반시도 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -72,7 +74,7 @@ class che_모반시도 extends Command\GeneralCommand{
$lordName = $lordGeneral->getName();
$nationName = $this->nation['name'];
$logger = $general->getLogger();
$lordLogger = $lordGeneral->getLogger();
@@ -82,7 +84,7 @@ class che_모반시도 extends Command\GeneralCommand{
$lordGeneral->setVar('officer_city', 0);
$lordGeneral->multiplyVar('experience', 0.7);
$josaYi = JosaUtil::pick($generalName, '이');
$logger->pushGlobalHistoryLog("<Y><b>【모반】</b></><Y>{$generalName}</>{$josaYi} <D><b>{$nationName}</b></>의 군주 자리를 찬탈했습니다.");
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <Y>{$lordName}</>에게서 군주자리를 찬탈");
@@ -95,11 +97,12 @@ class che_모반시도 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
$lordGeneral->applyDB($db);
return true;
}
}
+10 -7
View File
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst,
LastTurn,
@@ -13,6 +13,7 @@ use \sammo\{
use function \sammo\getDomesticExpLevelBonus;
use function \sammo\CriticalScoreEx;
use function sammo\tryUniqueItemLottery;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
@@ -33,9 +34,9 @@ class che_물자조달 extends Command\GeneralCommand{
$this->setCity();
$this->setNation();
$this->fullConditionConstraints=[
ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::SuppliedCity()
@@ -50,7 +51,7 @@ class che_물자조달 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -84,11 +85,11 @@ class che_물자조달 extends Command\GeneralCommand{
'normal'=>0.6
]);
$score *= CriticalScoreEx($pick);
$score = Util::round($score);
$scoreText = number_format($score, 0);
$logger = $general->getLogger();
if($pick == 'fail'){
@@ -120,10 +121,12 @@ class che_물자조달 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
return true;
}
}
+6 -5
View File
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -15,7 +15,7 @@ use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst;
use function sammo\DeleteConflict;
use function sammo\refreshNationStaticInfo;
use function sammo\tryRollbackInheritUniqueItem;
class che_방랑 extends Command\GeneralCommand{
static protected $actionName = '방랑';
@@ -34,7 +34,7 @@ class che_방랑 extends Command\GeneralCommand{
$this->setNation();
$relYear = $env['year'] - $env['startyear'];
$this->fullConditionConstraints=[
ConstraintHelper::BeLord(),
ConstraintHelper::NotWanderingNation(),
@@ -48,7 +48,7 @@ class che_방랑 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -85,7 +85,7 @@ class che_방랑 extends Command\GeneralCommand{
$logger->pushGlobalHistoryLog("<R><b>【방랑】</b></><D><b>{$generalName}</b></>{$josaUn} <R>방랑</>의 길을 떠납니다.");
$logger->pushGeneralHistoryLog("<D><b>{$nationName}</b></>{$josaUl} 버리고 방랑");
//분쟁기록 모두 지움
DeleteConflict($nationID);
// 국명, 색깔 바꿈 국가 레벨 0, 성향리셋, 기술0
@@ -123,6 +123,7 @@ class che_방랑 extends Command\GeneralCommand{
refreshNationStaticInfo();
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
return true;
+2
View File
@@ -20,6 +20,7 @@ use function\sammo\tryUniqueItemLottery;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use function sammo\tryRollbackInheritUniqueItem;
class che_선양 extends Command\GeneralCommand
{
@@ -136,6 +137,7 @@ class che_선양 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
$destGeneral->applyDB($db);
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -13,6 +13,8 @@ use \sammo\{
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use function sammo\tryRollbackInheritUniqueItem;
class che_소집해제 extends Command\GeneralCommand{
static protected $actionName = '소집해제';
@@ -27,7 +29,7 @@ class che_소집해제 extends Command\GeneralCommand{
$this->setCity();
$this->setNation();
$this->fullConditionConstraints=[
ConstraintHelper::ReqGeneralCrew(),
];
@@ -43,7 +45,7 @@ class che_소집해제 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -70,7 +72,7 @@ class che_소집해제 extends Command\GeneralCommand{
$exp = 70;
$ded = 100;
$db->update('city', [
'pop'=>$db->sqleval('pop + %i', $crew)
], 'city=%i', $general->getCityID());
@@ -80,10 +82,11 @@ class che_소집해제 extends Command\GeneralCommand{
$general->addDedication($ded);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
return true;
}
}
+7 -6
View File
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -13,7 +13,7 @@ use \sammo\{
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use function sammo\tryRollbackInheritUniqueItem;
class che_요양 extends Command\GeneralCommand{
static protected $actionName = '요양';
@@ -28,7 +28,7 @@ class che_요양 extends Command\GeneralCommand{
$general = $this->generalObj;
$this->setNation();
$this->fullConditionConstraints=[
];
@@ -37,7 +37,7 @@ class che_요양 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -56,7 +56,7 @@ class che_요양 extends Command\GeneralCommand{
$general = $this->generalObj;
$date = $general->getTurnTime($general::TURNTIME_HM);
$crew = $general->getVar('crew');
$logger = $general->getLogger();
@@ -71,10 +71,11 @@ class che_요양 extends Command\GeneralCommand{
$general->addDedication($ded);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
return true;
}
}
+3
View File
@@ -13,6 +13,7 @@ use \sammo\LastTurn;
use \sammo\Command;
use function \sammo\printCitiesBasedOnDistance;
use function sammo\tryUniqueItemLottery;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
@@ -169,6 +170,8 @@ class che_이동 extends Command\GeneralCommand
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
return true;
@@ -5,7 +5,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -13,6 +13,7 @@ use \sammo\{
};
use function \sammo\buildItemClass;
use function sammo\tryUniqueItemLottery;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
@@ -97,14 +98,14 @@ class che_장비매매 extends Command\GeneralCommand{
if(!$this->isArgValid){
return [0, 0];
}
$itemCode = $this->arg['itemCode'];
$itemObj = buildItemClass($itemCode);
$reqGold = $itemObj->getCost();
return [$reqGold, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -176,6 +177,7 @@ class che_장비매매 extends Command\GeneralCommand{
$general->addExperience($exp);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
return true;
@@ -208,7 +210,7 @@ $('#customSubmit').click(function(){
현재 구입 불가능한 것은 <font color=red>붉은색</font>으로 표시됩니다.<br>
현재 도시 치안 : <?=$citySecu?> &nbsp;&nbsp;&nbsp;현재 자금 : <?=$gold?><br>
장비 : <select class='formInput' name="itemCode" id="itemCode" onchange='updateItemType();' size='1' style='color:white;background-color:black;'>
<?php foreach(GameConst::$allItems as $itemType=>$itemCategories):
<?php foreach(GameConst::$allItems as $itemType=>$itemCategories):
//매각
$typeName = static::$itemMap[$itemType];
?>
+3
View File
@@ -16,6 +16,7 @@ use \sammo\Command;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use function sammo\tryUniqueItemLottery;
class che_증여 extends Command\GeneralCommand
{
@@ -168,6 +169,8 @@ class che_증여 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
$destGeneral->applyDB($db);
+2
View File
@@ -15,6 +15,7 @@ use \sammo\Json;
use function \sammo\searchDistance;
use function \sammo\printCitiesBasedOnDistance;
use function sammo\tryRollbackInheritUniqueItem;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
@@ -217,6 +218,7 @@ class che_첩보 extends Command\GeneralCommand
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
return true;
+8 -7
View File
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -14,7 +14,7 @@ use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst;
use function sammo\tryRollbackInheritUniqueItem;
class che_하야 extends Command\GeneralCommand{
static protected $actionName = '하야';
@@ -32,7 +32,7 @@ class che_하야 extends Command\GeneralCommand{
$this->setNation();
$relYear = $env['year'] - $env['startyear'];
$this->fullConditionConstraints=[
ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotOpeningPart($relYear),
@@ -43,7 +43,7 @@ class che_하야 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -67,7 +67,7 @@ class che_하야 extends Command\GeneralCommand{
$nationID = $this->nation['nation'];
$nationName = $this->nation['name'];
$logger = $general->getLogger();
$logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 하야했습니다. <1>$date</>");
@@ -101,13 +101,14 @@ class che_하야 extends Command\GeneralCommand{
$general->setVar('officer_city', 0);
$general->setVar('belong', 0);
$general->setVar('makelimit', 12);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
return true;
}
}
+6 -7
View File
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
General,
General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -16,13 +16,12 @@ use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst;
use function sammo\refreshNationStaticInfo;
use function sammo\deleteNation;
use function sammo\tryRollbackInheritUniqueItem;
class che_해산 extends Command\GeneralCommand{
static protected $actionName = '해산';
protected function argTest():bool{
protected function argTest():bool{
$this->arg = [];
return true;
@@ -45,7 +44,7 @@ class che_해산 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
public function getPreReqTurn():int{
return 0;
}
@@ -96,11 +95,11 @@ class che_해산 extends Command\GeneralCommand{
$oldGeneral->setVar('makelimit', 12);
$oldGeneral->applyDB($db);
}
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
return true;
}
}
+3
View File
@@ -15,6 +15,7 @@ use \sammo\Command;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use function sammo\tryUniqueItemLottery;
class che_헌납 extends Command\GeneralCommand
{
@@ -144,6 +145,8 @@ class che_헌납 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryUniqueItemLottery($general);
$general->applyDB($db);
return true;
+3
View File
@@ -14,6 +14,7 @@ use \sammo\Command;
use function \sammo\searchDistance;
use function \sammo\printCitiesBasedOnDistance;
use function sammo\tryRollbackInheritUniqueItem;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
@@ -294,6 +295,7 @@ class che_화계 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
return false;
}
@@ -327,6 +329,7 @@ class che_화계 extends Command\GeneralCommand
$general->increaseRankVar('firenum', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db);
return true;
+4 -2
View File
@@ -7,9 +7,11 @@ use \sammo\JosaUtil;
use \sammo\LastTurn;
use \sammo\DB;
use function sammo\tryRollbackInheritUniqueItem;
class 휴식 extends Command\GeneralCommand{
static protected $actionName = '휴식';
protected function argTest():bool{
return true;
}
@@ -39,7 +41,7 @@ class 휴식 extends Command\GeneralCommand{
$logger->pushGeneralActionLog("아무것도 실행하지 않았습니다. <1>$date</>");
$this->setResultTurn(new LastTurn());
tryRollbackInheritUniqueItem($general);
$general->applyDB(DB::db());
return true;
}
+4
View File
@@ -25,6 +25,10 @@ trait DefaultAction{
return $value;
}
public function onCalcOpposeStat(General $general, string $statName, $value, $aux=null){
return $value;
}
public function onCalcStrategic(string $turnType, string $varType, $value){
return $value;
}
+8
View File
@@ -34,6 +34,14 @@ class DummyGeneral extends General{
return new WarUnitTriggerCaller();
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
return $value;
}
public function onCalcOpposeStat(General $general, string $statName, $value, $aux=null){
return $value;
}
function applyDB($db):bool{
if($this->logger){
$this->initLogger(1, 1);
+72 -56
View File
@@ -1,15 +1,16 @@
<?php
namespace sammo;
class GameConstBase
{
/** @var string 게임명 */
public static $title = "삼국지 모의전투 PHP HiDCHe";
/** @var string 코드 아래에 붙는 설명 코드 */
public static $banner = "KOEI의 이미지를 사용, 응용하였습니다 / 제작 : HideD(hided62@gmail.com) / <a href='https://sam.hided.net/wiki/hidche/credit' target='_blank' style='color:white;text-decoration: underline;'>Credit</a>";
/** @var string 사용중인 지도명 */
public static $mapName = 'che';
/** @var string 사용중인 유닛셋 */
/** @var string 게임명 */
public static $title = "삼국지 모의전투 PHP HiDCHe";
/** @var string 코드 아래에 붙는 설명 코드 */
public static $banner = "KOEI의 이미지를 사용, 응용하였습니다 / 제작 : HideD(hided62@gmail.com) / <a href='https://sam.hided.net/wiki/hidche/credit' target='_blank' style='color:white;text-decoration: underline;'>Credit</a>";
/** @var string 사용중인 지도명 */
public static $mapName = 'che';
/** @var string 사용중인 유닛셋 */
public static $unitSet = 'che';
/** @var int 내정시 최하 민심 설정*/
public static $develrate = 50;
@@ -137,12 +138,17 @@ class GameConstBase
public static $maxChiefTurn = 12;
public static $statGradeLevel = 5;
/** @var int 초반 제한 기간 */
public static $openingPartYear = 3;
/** @var int 거병,임관 제한 기간 */
public static $joinActionLimit = 12;
/** @var int 장수 생성시 능력치 최소 보너스 */
public static $bornMinStatBonus = 3;
/** @var int 장수 생성시 능력치 최대 보너스 */
public static $bornMaxStatBonus = 5;
/** @var array 선택 가능한 국가 성향 */
public static $availableNationType = [
'che_도적', 'che_명가', 'che_음양가', 'che_종횡가', 'che_불가', 'che_오두미도', 'che_태평도', 'che_도가',
@@ -166,83 +172,93 @@ class GameConstBase
public static $defaultSpecialWar = 'None';
/** @var array 선택 가능한 장수 전투 특기 */
public static $availableSpecialWar = [
'che_귀병', 'che_신산', 'che_환술', 'che_집중', 'che_신중', 'che_반계',
'che_귀병', 'che_신산', 'che_환술', 'che_집중', 'che_신중', 'che_반계',
'che_보병', 'che_궁병', 'che_기병', 'che_공성',
'che_돌격', 'che_무쌍', 'che_견고', 'che_위압',
'che_돌격', 'che_무쌍', 'che_견고', 'che_위압',
'che_저격', 'che_필살', 'che_징병', 'che_의술', 'che_격노', 'che_척사',
];
/** @var array 선택할 수 없으나 게임 내에 유효한 장수 전투 특기 */
public static $optionalSpecialWar = [
'None',
];
/** @var string 기본 성향(공용) */
public static $neutralPersonality = 'None';
/** @var array 선택 가능한 성향 */
public static $availablePersonality = [
'che_안전', 'che_유지', 'che_재간', 'che_출세', 'che_할거', 'che_정복',
'che_패권', 'che_의협', 'che_대의', 'che_왕좌'
'che_패권', 'che_의협', 'che_대의', 'che_왕좌'
];
/** @var array 존재하는 모든 성향 */
public static $optionalPersonality = [
'che_은둔', 'None'
];
public static $inheritBornSpecialPoint = 12000;
public static $inheritBornTurntimePoint = 3000;
public static $inheritBornCityPoint = 1000;
public static $inheritBornStatPoint = 1000;
public static $inheritItemUniqueMinPoint = 5000;
public static $inheritItemRandomPoint = 3000;
public static $inheritBuffPoints = [0, 250, 750, 1500, 2500, 3750];
public static $inheritSpecificSpecialPoint = 5000;
public static $inheritResetAttrPointBase = [1000, 1000, 2000, 3000];//필요하면 늘려서 쓰기
public static $allItems = [
'horse' => [
'che_명마_01_노기'=>0, 'che_명마_02_조랑'=>0, 'che_명마_03_노새'=>0,
'che_명마_04_나귀'=>0, 'che_명마_05_갈색마'=>0, 'che_명마_06_흑색마'=>0,
'che_명마_07_백마'=>2, 'che_명마_07_기주마'=>2,
'che_명마_08_양주마'=>2, 'che_명마_09_과하마'=>2,
'che_명마_10_대완마'=>2, 'che_명마_11_서량마'=>2,
'che_명마_12_사륜거'=>2, 'che_명마_13_절영'=>1, 'che_명마_13_적로'=>1,
'che_명마_14_적란마'=>1, 'che_명마_14_조황비전'=>1, 'che_명마_15_한혈마'=>1, 'che_명마_15_적토마'=>1,
'che_명마_01_노기' => 0, 'che_명마_02_조랑' => 0, 'che_명마_03_노새' => 0,
'che_명마_04_나귀' => 0, 'che_명마_05_갈색마' => 0, 'che_명마_06_흑색마' => 0,
'che_명마_07_백마' => 2, 'che_명마_07_기주마' => 2,
'che_명마_08_양주마' => 2, 'che_명마_09_과하마' => 2,
'che_명마_10_대완마' => 2, 'che_명마_11_서량마' => 2,
'che_명마_12_사륜거' => 2, 'che_명마_13_절영' => 1, 'che_명마_13_적로' => 1,
'che_명마_14_적란마' => 1, 'che_명마_14_조황비전' => 1, 'che_명마_15_한혈마' => 1, 'che_명마_15_적토마' => 1,
],
'weapon' => [
'che_무기_01_단도'=>0, 'che_무기_02_단궁'=>0, 'che_무기_03_단극'=>0,
'che_무기_04_목검'=>0, 'che_무기_05_죽창'=>0, 'che_무기_06_소부'=>0,
'che_무기_07_동추'=>1, 'che_무기_07_철편'=>1, 'che_무기_07_철쇄'=>1, 'che_무기_07_맥궁'=>1,
'che_무기_08_유성추'=>1, 'che_무기_08_철질여골'=>1, 'che_무기_09_쌍철극'=>1, 'che_무기_09_동호비궁'=>1, 'che_무기_10_삼첨도'=>1, 'che_무기_10_대부'=>1, 'che_무기_11_고정도'=>1, 'che_무기_11_이광궁'=>1, 'che_무기_12_철척사모'=>1, 'che_무기_12_칠성검'=>1, 'che_무기_13_사모'=>1, 'che_무기_13_양유기궁'=>1,
'che_무기_14_언월도'=>1, 'che_무기_14_방천화극'=>1, 'che_무기_15_청홍검'=>1, 'che_무기_15_의천검'=>1
'che_무기_01_단도' => 0, 'che_무기_02_단궁' => 0, 'che_무기_03_단극' => 0,
'che_무기_04_목검' => 0, 'che_무기_05_죽창' => 0, 'che_무기_06_소부' => 0,
'che_무기_07_동추' => 1, 'che_무기_07_철편' => 1, 'che_무기_07_철쇄' => 1, 'che_무기_07_맥궁' => 1,
'che_무기_08_유성추' => 1, 'che_무기_08_철질여골' => 1, 'che_무기_09_쌍철극' => 1, 'che_무기_09_동호비궁' => 1, 'che_무기_10_삼첨도' => 1, 'che_무기_10_대부' => 1, 'che_무기_11_고정도' => 1, 'che_무기_11_이광궁' => 1, 'che_무기_12_철척사모' => 1, 'che_무기_12_칠성검' => 1, 'che_무기_13_사모' => 1, 'che_무기_13_양유기궁' => 1,
'che_무기_14_언월도' => 1, 'che_무기_14_방천화극' => 1, 'che_무기_15_청홍검' => 1, 'che_무기_15_의천검' => 1
],
'book' => [
'che_서적_01_효경전'=>0, 'che_서적_02_회남자'=>0, 'che_서적_03_변도론'=>0,
'che_서적_04_건상역주'=>0, 'che_서적_05_여씨춘추'=>0, 'che_서적_06_사민월령'=>0,
'che_서적_01_효경전' => 0, 'che_서적_02_회남자' => 0, 'che_서적_03_변도론' => 0,
'che_서적_04_건상역주' => 0, 'che_서적_05_여씨춘추' => 0, 'che_서적_06_사민월령' => 0,
'che_서적_07_위료자'=>1, 'che_서적_07_사마법'=>1, 'che_서적_07_한서'=>1, 'che_서적_07_논어'=>1,
'che_서적_08_전론'=>1, 'che_서적_08_사기'=>1, 'che_서적_09_장자'=>1, 'che_서적_09_역경'=>1,
'che_서적_10_시경'=>1, 'che_서적_10_구국론'=>1, 'che_서적_11_상군서'=>1, 'che_서적_11_춘추전'=>1,
'che_서적_12_산해경'=>1, 'che_서적_12_맹덕신서'=>1, 'che_서적_13_관자'=>1, 'che_서적_13_병법24편'=>1,
'che_서적_14_한비자'=>1, 'che_서적_14_오자병법'=>1, 'che_서적_15_노자'=>1, 'che_서적_15_손자병법'=>1,
'che_서적_07_위료자' => 1, 'che_서적_07_사마법' => 1, 'che_서적_07_한서' => 1, 'che_서적_07_논어' => 1,
'che_서적_08_전론' => 1, 'che_서적_08_사기' => 1, 'che_서적_09_장자' => 1, 'che_서적_09_역경' => 1,
'che_서적_10_시경' => 1, 'che_서적_10_구국론' => 1, 'che_서적_11_상군서' => 1, 'che_서적_11_춘추전' => 1,
'che_서적_12_산해경' => 1, 'che_서적_12_맹덕신서' => 1, 'che_서적_13_관자' => 1, 'che_서적_13_병법24편' => 1,
'che_서적_14_한비자' => 1, 'che_서적_14_오자병법' => 1, 'che_서적_15_노자' => 1, 'che_서적_15_손자병법' => 1,
],
'item' => [
'che_치료_환약'=>0, 'che_저격_수극'=>0, 'che_사기_탁주'=>0,
'che_훈련_청주'=>0, 'che_계략_이추'=>0, 'che_계략_향낭'=>0,
'che_치료_환약' => 0, 'che_저격_수극' => 0, 'che_사기_탁주' => 0,
'che_훈련_청주' => 0, 'che_계략_이추' => 0, 'che_계략_향낭' => 0,
'che_의술_청낭서'=>1, 'che_의술_태평청령'=>1, 'che_의술_상한잡병론'=>1,
'che_부적_태현청생부'=>1,
'che_저격_매화수전'=>1, 'che_저격_비도'=>1,
'che_계략_육도'=>1, 'che_계략_삼략'=>1,
'che_반계_백우선'=>1,
'che_행동_서촉지형도'=>1,
'che_의술_청낭서' => 1, 'che_의술_태평청령' => 1, 'che_의술_상한잡병론' => 1,
'che_부적_태현청생부' => 1,
'che_저격_매화수전' => 1, 'che_저격_비도' => 1,
'che_계략_육도' => 1, 'che_계략_삼략' => 1,
'che_반계_백우선' => 1,
'che_행동_서촉지형도' => 1,
'che_훈련_과실주'=>1, 'che_훈련_이강주'=>1, 'che_사기_두강주'=>1, 'che_사기_보령압주'=>1,
'che_훈련_철벽서'=>1, 'che_훈련_단결도'=>1, 'che_사기_춘화첩'=>1, 'che_사기_초선화'=>1,
'che_회피_태평요술'=>1, 'che_회피_둔갑천서'=>1,
'che_훈련_과실주' => 1, 'che_훈련_이강주' => 1, 'che_사기_두강주' => 1, 'che_사기_보령압주' => 1,
'che_훈련_철벽서' => 1, 'che_훈련_단결도' => 1, 'che_사기_춘화첩' => 1, 'che_사기_초선화' => 1,
'che_회피_태평요술' => 1, 'che_회피_둔갑천서' => 1,
]
];
/** @var array 선택 가능한 커맨드 */
public static $availableGeneralCommand = [
''=>[
'' => [
'휴식',
'che_요양'
],
'내정'=>[
'내정' => [
'che_농지개간',
'che_상업투자',
'che_기술연구',
@@ -253,7 +269,7 @@ class GameConstBase
'che_주민선정',
'che_물자조달',
],
'군사'=>[
'군사' => [
'che_소집해제',
'che_첩보',
'che_징병',
@@ -262,7 +278,7 @@ class GameConstBase
'che_사기진작',
'che_출병',
],
'인사'=>[
'인사' => [
'che_이동',
'che_강행',
'che_인재탐색',
@@ -273,13 +289,13 @@ class GameConstBase
'che_랜덤임관',
'che_장수대상임관',
],
'계략'=>[
'계략' => [
'che_화계',
'che_파괴',
'che_탈취',
'che_선동',
],
'개인'=>[
'개인' => [
'che_내정특기초기화',
'che_전투특기초기화',
'che_단련',
@@ -301,28 +317,28 @@ class GameConstBase
/** @var array 선택 가능한 커맨드 */
public static $availableChiefCommand = [
'휴식'=>[
'휴식' => [
'휴식',
],
'인사'=>[
'인사' => [
'che_발령',
'che_포상',
'che_몰수',
],
'외교'=>[
'외교' => [
'che_물자원조',
'che_불가침제의',
'che_선전포고',
'che_종전제의',
'che_불가침파기제의',
],
'특수'=>[
'특수' => [
'che_초토화',
'che_천도',
'che_증축',
'che_감축',
],
'전략'=>[
'전략' => [
'che_필사즉생',
'che_백성동원',
'che_수몰',
@@ -331,7 +347,7 @@ class GameConstBase
'che_이호경식',
'che_급습',
],
'기타'=>[
'기타' => [
'che_피장파장',
'che_국기변경',
'che_국호변경',
+485 -339
View File
@@ -5,7 +5,8 @@ namespace sammo;
use sammo\Command\GeneralCommand;
use sammo\WarUnitTrigger as WarUnitTrigger;
class General implements iAction{
class General implements iAction
{
use LazyVarUpdater;
protected $raw = [];
@@ -35,33 +36,35 @@ class General implements iAction{
protected $personalityObj = null;
/** @var iAction[] */
protected $itemObjs = [];
/** @var iAction */
protected $inheritBuffObj = null;
protected $lastTurn = null;
protected $resultTurn = null;
const RANK_COLUMN = [
'firenum'=>1, 'warnum'=>1, 'killnum'=>1, 'deathnum'=>1, 'killcrew'=>1, 'deathcrew'=>1,
'ttw'=>1, 'ttd'=>1, 'ttl'=>1, 'ttg'=>1, 'ttp'=>1,
'tlw'=>1, 'tld'=>1, 'tll'=>1, 'tlg'=>1, 'tlp'=>1,
'tsw'=>1, 'tsd'=>1, 'tsl'=>1, 'tsg'=>1, 'tsp'=>1,
'tiw'=>1, 'tid'=>1, 'til'=>1, 'tig'=>1, 'tip'=>1,
'betwin'=>1, 'betgold'=>1, 'betwingold'=>1,
'killcrew_person'=>1, 'deathcrew_person'=>1,
'occupied'=>1,
'firenum' => 1, 'warnum' => 1, 'killnum' => 1, 'deathnum' => 1, 'killcrew' => 1, 'deathcrew' => 1,
'ttw' => 1, 'ttd' => 1, 'ttl' => 1, 'ttg' => 1, 'ttp' => 1,
'tlw' => 1, 'tld' => 1, 'tll' => 1, 'tlg' => 1, 'tlp' => 1,
'tsw' => 1, 'tsd' => 1, 'tsl' => 1, 'tsg' => 1, 'tsp' => 1,
'tiw' => 1, 'tid' => 1, 'til' => 1, 'tig' => 1, 'tip' => 1,
'betwin' => 1, 'betgold' => 1, 'betwingold' => 1,
'killcrew_person' => 1, 'deathcrew_person' => 1,
'occupied' => 1,
];
const INHERITANCE_KEY = [
'previous'=>[true, 1, '기존 포인트'],
'lived_month'=>[true, 1, '생존'],
'max_belong'=>[false, 10, '최대 임관년 수'],
'max_domestic_critical'=>[true, 1, '최대 연속 내정 성공'],
'snipe_combat'=>[true, 10, '병종 상성 우위 횟수'],
'combat'=>[['rank', 'warnum'], 5, '전투 횟수'],
'sabotage'=>[['rank', 'firenum'], 20, '계략 성공 횟수'],
'unifier'=>[true, 1, '천통 기여'],
'dex'=>[false, 0.001, '숙련도'],
'tournament'=>[true, 1, '토너먼트'],
'betting'=>[false, 10, '베팅 당첨'],
'previous' => [true, 1, '기존 포인트'],
'lived_month' => [true, 1, '생존'],
'max_belong' => [false, 10, '최대 임관년 수'],
'max_domestic_critical' => [true, 1, '최대 연속 내정 성공'],
'snipe_combat' => [true, 10, '병종 상성 우위 횟수'],
'combat' => [['rank', 'warnum'], 5, '전투 횟수'],
'sabotage' => [['rank', 'firenum'], 20, '계략 성공 횟수'],
'unifier' => [true, 1, '천통 기여'],
'dex' => [false, 0.001, '숙련도'],
'tournament' => [true, 1, '토너먼트'],
'betting' => [false, 10, '베팅 당첨'],
];
const TURNTIME_FULL_MS = -1;
@@ -73,19 +76,19 @@ class General implements iAction{
protected static $prohibitedDirectUpdateVars = [
//Reason: iAction
'leadership'=>1,
'power'=>1,
'intel'=>1,
'nation'=>2,
'officer_level'=>1,
'leadership' => 1,
'power' => 1,
'intel' => 1,
'nation' => 2,
'officer_level' => 1,
//NOTE: officerLevelObj로 인해 국가의 '레벨'이 바뀌는 것도 조심해야 하나, 국가 레벨의 변경은 월 초/말에만 일어남.
'special'=>1,
'special2'=>1,
'personal'=>1,
'horse'=>1,
'weapon'=>1,
'book'=>1,
'item'=>1
'special' => 1,
'special2' => 1,
'personal' => 1,
'horse' => 1,
'weapon' => 1,
'book' => 1,
'item' => 1
];
@@ -96,10 +99,11 @@ class General implements iAction{
* @param int|null $month 게임
* @param bool $fullConstruct iAction, ActionLogger 초기화 여부, false인 경우 no, name, city, nation, officer_level 정도로 초기화 가능
*/
public function __construct(array $raw, ?array $rawRank, ?array $city, ?array $nation, ?int $year, ?int $month, bool $fullConstruct=true){
public function __construct(array $raw, ?array $rawRank, ?array $city, ?array $nation, ?int $year, ?int $month, bool $fullConstruct = true)
{
//TODO: 밖에서 가져오도록 하면 버그 확률이 높아짐. 필요한 raw 값을 직접 구해야함.
if($nation === null){
if ($nation === null) {
$nation = getNationStaticInfo($raw['nation']);
}
@@ -107,20 +111,20 @@ class General implements iAction{
$this->rawCity = $city;
$this->resultTurn = new LastTurn();
if(key_exists('last_turn', $this->raw)){
if (key_exists('last_turn', $this->raw)) {
$this->lastTurn = LastTurn::fromJson($this->raw['last_turn']);
$this->resultTurn = $this->lastTurn->duplicate();
}
if($year !== null && $month !== null){
if ($year !== null && $month !== null) {
$this->initLogger($year, $month);
}
if($rawRank){
if ($rawRank) {
$this->rankVarRead = $rawRank;
}
if(!$fullConstruct){
if (!$fullConstruct) {
return;
}
@@ -136,9 +140,17 @@ class General implements iAction{
$this->itemObjs['weapon'] = buildItemClass($raw['weapon']);
$this->itemObjs['book'] = buildItemClass($raw['book']);
$this->itemObjs['item'] = buildItemClass($raw['item']);
if (key_exists('aux', $this->raw)) {
$rawInheritBuff = $this->getAuxVar('inheritBuff');
if ($rawInheritBuff !== null) {
$this->inheritBuffObj = new TriggerInheritBuff($rawInheritBuff);
}
}
}
function initLogger(int $year, int $month){
function initLogger(int $year, int $month)
{
$this->logger = new ActionLogger(
$this->getVar('no'),
$this->getVar('nation'),
@@ -148,17 +160,27 @@ class General implements iAction{
);
}
function getTurnTime(int $short=self::TURNTIME_FULL_MS){
function getTurnTime(int $short = self::TURNTIME_FULL_MS)
{
return [
self::TURNTIME_FULL_MS=>function($turntime){return $turntime;},
self::TURNTIME_FULL=>function($turntime){return substr($turntime, 0, 19);},
self::TURNTIME_HMS=>function($turntime){return substr($turntime, 11, 8);},
self::TURNTIME_HM=>function($turntime){return substr($turntime, 11, 5);},
self::TURNTIME_FULL_MS => function ($turntime) {
return $turntime;
},
self::TURNTIME_FULL => function ($turntime) {
return substr($turntime, 0, 19);
},
self::TURNTIME_HMS => function ($turntime) {
return substr($turntime, 11, 8);
},
self::TURNTIME_HM => function ($turntime) {
return substr($turntime, 11, 5);
},
][$short]($this->getVar('turntime'));
}
function setItem(string $itemKey='item', ?string $itemCode){
if($itemCode === null){
function setItem(string $itemKey = 'item', ?string $itemCode)
{
if ($itemCode === null) {
$this->deleteItem($itemKey);
}
@@ -166,50 +188,61 @@ class General implements iAction{
$this->itemObjs[$itemKey] = buildItemClass($itemCode);
}
function deleteItem(string $itemKey='item'){
function deleteItem(string $itemKey = 'item')
{
$this->setVar($itemKey, 'None');
$this->itemObjs[$itemKey] = new ActionItem\None();
}
function getItem(string $itemKey='item'):BaseItem{
function getItem(string $itemKey = 'item'): BaseItem
{
return $this->itemObjs[$itemKey];
}
function getNPCType():int{
function getNPCType(): int
{
return $this->raw['npc'];
}
/** @return BaseItem[] */
function getItems():array{
function getItems(): array
{
return $this->itemObjs;
}
function getPersonality():iAction{
function getPersonality(): iAction
{
return $this->personalityObj;
}
function getSpecialDomestic():iAction{
function getSpecialDomestic(): iAction
{
return $this->specialDomesticObj;
}
function getSpecialWar():iAction{
function getSpecialWar(): iAction
{
return $this->specialWarObj;
}
function getLastTurn():LastTurn{
function getLastTurn(): LastTurn
{
return $this->lastTurn;
}
function _setResultTurn(LastTurn $resultTurn){
function _setResultTurn(LastTurn $resultTurn)
{
$this->resultTurn = $resultTurn;
}
function getResultTurn():LastTurn{
function getResultTurn(): LastTurn
{
return $this->resultTurn;
}
function clearActivatedSkill(){
foreach ($this->activatedSkill as $skillName=>$state) {
function clearActivatedSkill()
{
foreach ($this->activatedSkill as $skillName => $state) {
if (!$state) {
continue;
}
@@ -223,86 +256,103 @@ class General implements iAction{
$this->activatedSkill = [];
}
function getActivatedSkillLog():array{
function getActivatedSkillLog(): array
{
return $this->logActivatedSkill;
}
function hasActivatedSkill(string $skillName):bool{
function hasActivatedSkill(string $skillName): bool
{
return $this->activatedSkill[$skillName] ?? false;
}
function activateSkill(... $skillNames){
foreach($skillNames as $skillName){
function activateSkill(...$skillNames)
{
foreach ($skillNames as $skillName) {
$this->activatedSkill[$skillName] = true;
}
}
function deactivateSkill(... $skillNames){
foreach($skillNames as $skillName){
function deactivateSkill(...$skillNames)
{
foreach ($skillNames as $skillName) {
$this->activatedSkill[$skillName] = false;
}
}
function getName():string{
function getName(): string
{
return $this->raw['name'];
}
function getInfo():string{
function getInfo(): string
{
//iAction용 info로는 적절하지 않음
return '';
}
function getID():int{
function getID(): int
{
return $this->raw['no'];
}
function getRawCity():?array{
function getRawCity(): ?array
{
return $this->rawCity;
}
function setRawCity(?array $city){
function setRawCity(?array $city)
{
$this->rawCity = $city;
}
function getCityID():int{
function getCityID(): int
{
return $this->raw['city'];
}
function getNationID():int{
function getNationID(): int
{
return $this->raw['nation'];
}
function getStaticNation():array{
function getStaticNation(): array
{
return getNationStaticInfo($this->raw['nation']);
}
function getLogger():?ActionLogger{
function getLogger(): ?ActionLogger
{
return $this->logger;
}
public function getNationTypeObj():iAction{
public function getNationTypeObj(): iAction
{
return $this->nationType;
}
public function getOfficerLevelObj():iAction{
public function getOfficerLevelObj(): iAction
{
return $this->officerLevelObj;
}
function getCrewTypeObj():GameUnitDetail{
function getCrewTypeObj(): GameUnitDetail
{
$crewType = GameUnitConst::byID($this->getVar('crewtype'));
if($crewType === null){
throw new \InvalidArgumentException('Invalid CrewType:'.$this->getVar('crewtype'));
if ($crewType === null) {
throw new \InvalidArgumentException('Invalid CrewType:' . $this->getVar('crewtype'));
}
return $crewType;
}
function calcRecentWarTurn(int $turnTerm):int{
function calcRecentWarTurn(int $turnTerm): int
{
$cacheKey = "recent_war_turn_{$turnTerm}";
if(key_exists($cacheKey, $this->calcCache)){
if (key_exists($cacheKey, $this->calcCache)) {
return $this->calcCache[$cacheKey];
}
if(!$this->getVar('recent_war')){
$result = 12*1000;
if (!$this->getVar('recent_war')) {
$result = 12 * 1000;
$this->calcCache[$cacheKey] = $result;
return $result;
}
@@ -310,7 +360,7 @@ class General implements iAction{
$turnNow = new \DateTimeImmutable($this->getVar('turntime'));
$secDiff = TimeUtil::DateIntervalToSeconds($recwar->diff($turnNow));
if($secDiff <= 0){
if ($secDiff <= 0) {
$this->calcCache[$cacheKey] = 0;
return 0;
}
@@ -320,13 +370,14 @@ class General implements iAction{
return $result;
}
function getReservedTurn(int $turnIdx, array $env):GeneralCommand{
function getReservedTurn(int $turnIdx, array $env): GeneralCommand
{
$db = DB::db();
$rawCmd = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id = %i AND turn_idx = %i', $this->getID(), $turnIdx);
if(!$rawCmd){
if (!$rawCmd) {
return buildGeneralCommandClass(null, $this, $env);
}
return buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg']??null));
return buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg'] ?? null));
}
/**
@@ -336,13 +387,14 @@ class General implements iAction{
* @param array $env
* @return GeneralCommand[]
*/
public function getReservedTurnList(int $turnIdxFrom, int $turnIdxTo, array $env){
if($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn){
throw new \OutOfRangeException('$turnIdxFrom 범위 초과'.$turnIdxFrom);
public function getReservedTurnList(int $turnIdxFrom, int $turnIdxTo, array $env)
{
if ($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn) {
throw new \OutOfRangeException('$turnIdxFrom 범위 초과' . $turnIdxFrom);
}
if($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo){
throw new \OutOfRangeException('$turnIdxTo 범위 초과'.$turnIdxTo);
if ($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo) {
throw new \OutOfRangeException('$turnIdxTo 범위 초과' . $turnIdxTo);
}
$db = DB::db();
@@ -353,15 +405,15 @@ class General implements iAction{
$rawCmds = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id = %i AND %i <= turn_idx AND turn_idx < %i ORDER BY turn_idx ASC', $generalID, $turnIdxFrom, $turnIdxTo);
if(!$rawCmds){
foreach(Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx){
if (!$rawCmds) {
foreach (Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx) {
$result[$turnIdx] = buildGeneralCommandClass(null, $this, $env);
}
return $result;
}
foreach($rawCmds as $turnIdx=>$rawCmd){
$result[$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg']??null));
foreach ($rawCmds as $turnIdx => $rawCmd) {
$result[$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg'] ?? null));
}
return $result;
@@ -379,11 +431,12 @@ class General implements iAction{
* @return int|float 계산된 능력치
*/
protected function getStatValue(string $statName, $withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
protected function getStatValue(string $statName, $withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true): float
{
$cKey = "{$statName}_{$withInjury}_{$withIActionObj}_{$withStatAdjust}";
if(key_exists($cKey, $this->calcCache)){
if (key_exists($cKey, $this->calcCache)) {
$statValue = $this->calcCache[$cKey];
if($useFloor){
if ($useFloor) {
return Util::toInt($statValue);
}
return $statValue;
@@ -391,34 +444,34 @@ class General implements iAction{
$statValue = $this->getVar($statName);
if($withInjury){
if ($withInjury) {
$statValue *= (100 - $this->getVar('injury')) / 100;
}
if($withStatAdjust){
if($statName === 'strength'){
if ($withStatAdjust) {
if ($statName === 'strength') {
$statValue += Util::round($this->getStatValue('intel', $withInjury, $withIActionObj, false, false) / 4);
}
else if($statName === 'intel'){
} else if ($statName === 'intel') {
$statValue += Util::round($this->getStatValue('strength', $withInjury, $withIActionObj, false, false) / 4);
}
}
if($withIActionObj){
foreach([
if ($withIActionObj) {
foreach ([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj
] as $actionObj){
if($actionObj !== null){
$this->personalityObj,
$this->inheritBuffObj,
] as $actionObj) {
if ($actionObj !== null) {
$statValue = $actionObj->onCalcStat($this, $statName, $statValue);
}
}
foreach($this->itemObjs as $actionObj){
if($actionObj !== null){
foreach ($this->itemObjs as $actionObj) {
if ($actionObj !== null) {
$statValue = $actionObj->onCalcStat($this, $statName, $statValue);
}
}
@@ -426,54 +479,58 @@ class General implements iAction{
$this->calcCache[$cKey] = $statValue;
if($useFloor){
if ($useFloor) {
return Util::toInt($statValue);
}
return $statValue;
}
function getLeadership($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
function getLeadership($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true): float
{
return $this->getStatValue('leadership', $withInjury, $withIActionObj, $withStatAdjust, $useFloor);
}
function getStrength($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
function getStrength($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true): float
{
return $this->getStatValue('strength', $withInjury, $withIActionObj, $withStatAdjust, $useFloor);
}
function getIntel($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{
function getIntel($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true): float
{
return $this->getStatValue('intel', $withInjury, $withIActionObj, $withStatAdjust, $useFloor);
}
function getDex(GameUnitDetail $crewType){
function getDex(GameUnitDetail $crewType)
{
$armType = $crewType->armType;
if($armType == GameUnitConst::T_CASTLE){
if ($armType == GameUnitConst::T_CASTLE) {
$armType = GameUnitConst::T_SIEGE;
}
return $this->getVar("dex{$armType}");
}
function addDex(GameUnitDetail $crewType, float $exp, bool $affectTrainAtmos=false){
function addDex(GameUnitDetail $crewType, float $exp, bool $affectTrainAtmos = false)
{
$armType = $crewType->armType;
if($armType == GameUnitConst::T_CASTLE){
if ($armType == GameUnitConst::T_CASTLE) {
$armType = GameUnitConst::T_SIEGE;
}
if($armType < 0){
if ($armType < 0) {
return;
}
if($armType == GameUnitConst::T_WIZARD) {
if ($armType == GameUnitConst::T_WIZARD) {
$exp *= 0.9;
}
else if($armType == GameUnitConst::T_SIEGE) {
} else if ($armType == GameUnitConst::T_SIEGE) {
$exp *= 0.9;
}
if($affectTrainAtmos){
if ($affectTrainAtmos) {
$exp *= ($this->getVar('train') + $this->getVar('atmos')) / 200;
}
@@ -482,39 +539,39 @@ class General implements iAction{
$this->increaseVar($dexType, $exp);
}
function addExperience(float $experience, bool $affectTrigger=true){
if($affectTrigger){
function addExperience(float $experience, bool $affectTrigger = true)
{
if ($affectTrigger) {
$experience = $this->onCalcStat($this, 'experience', $experience);
}
$this->increaseVar('experience', $experience);
$nextExpLevel = getExpLevel($this->getVar('experience'));
$comp = $nextExpLevel <=> $this->getVar('explevel');
if($comp === 0){
if ($comp === 0) {
return;
}
$this->updateVar('explevel', $nextExpLevel);
$josaRo = JosaUtil::pick($nextExpLevel, '로');
if($comp > 0){
if ($comp > 0) {
$this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <C>레벨업</>!", ActionLogger::PLAIN);
}
else{
} else {
$this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <R>레벨다운</>!", ActionLogger::PLAIN);
}
}
function addDedication(float $dedication, bool $affectTrigger=true){
if($affectTrigger){
function addDedication(float $dedication, bool $affectTrigger = true)
{
if ($affectTrigger) {
$dedication = $this->onCalcStat($this, 'dedication', $dedication);
}
$this->increaseVar('dedication', $dedication);
$nextDedLevel = getDedLevel($this->getVar('dedication'));
$comp = $nextDedLevel <=> $this->getVar('dedlevel');
if($comp === 0){
if ($comp === 0) {
return;
}
@@ -524,20 +581,19 @@ class General implements iAction{
$billText = number_format(getBillByLevel($nextDedLevel));
$josaRoDed = JosaUtil::pick($dedLevelText, '로');
$josaRoBill = JosaUtil::pick($billText, '로');
if($comp > 0){
if ($comp > 0) {
$this->getLogger()->pushGeneralActionLog("<Y>{$dedLevelText}</>{$josaRoDed} <C>승급</>하여 봉록이 <C>{$billText}</>{$josaRoBill} <C>상승</>했습니다!", ActionLogger::PLAIN);
}
else{
} else {
$this->getLogger()->pushGeneralActionLog("<Y>{$dedLevelText}</>{$josaRoDed} <R>강등</>되어 봉록이 <C>{$billText}</>{$josaRoBill} <R>하락</>했습니다!", ActionLogger::PLAIN);
}
}
function updateVar(string $key, $value){
if(($this->raw[$key]??null) === $value){
function updateVar(string $key, $value)
{
if (($this->raw[$key] ?? null) === $value) {
return;
}
if(!key_exists($key, $this->updatedVar)){
if (!key_exists($key, $this->updatedVar)) {
$this->updatedVar[$key] = true;
}
$this->raw[$key] = $value;
@@ -547,39 +603,81 @@ class General implements iAction{
/**
* @param \MeekroDB $db
*/
function kill($db, bool $sendDyingMessage=true, ?string $dyingMessage=null){
function kill($db, bool $sendDyingMessage = true, ?string $dyingMessage = null)
{
$generalID = $this->getID();
$logger = $this->getLogger();
$generalName = $this->getName();
$this->mergeTotalInheritancePoint();
//유산포인트 관련 항목 환불
if ($this->getNPCType() < 2) {
$refundPoint = 0;
$userID = $this->getVar('owner');
$userLogger = new UserLogger($userID);
if ($this->getAuxVar('inheritRandomUnique')) {
$this->setAuxVar('inheritRandomUnique', null);
$userLogger->push(sprintf("사망으로 랜덤 유니크 구입 %d 포인트 반환", GameConst::$inheritItemRandomPoint), "inheritPoint");
$refundPoint += GameConst::$inheritItemRandomPoint;
}
$itemTrials = $this->getAuxVar('inheritUniqueTrial') ?? [];
foreach (array_keys($itemTrials) as $itemKey) {
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}");
$ownTrial = $trialStor->getValue("u{$userID}");
$itemObj = buildItemClass($itemKey);
$itemName = $itemObj->getName();
if (!$ownTrial) {
continue;
}
[,, $amount] = $ownTrial;
$trialStor->deleteValue("u{$userID}");
$userLogger->push("사망으로 {$itemName} 입찰에 사용한 {$amount} 포인트 반환", "inheritPoint");
$refundPoint += $amount;
}
if($this->getAuxVar('inheritSpecificSpecialWar')){
$this->setAuxVar('inheritSpecificSpecialWar', null);
$userLogger->push(sprintf("사망으로 전투 특기 지정 %d 포인트 반환", GameConst::$inheritSpecificSpecialPoint), "inheritPoint");
$refundPoint += GameConst::$inheritSpecificSpecialPoint;
}
if ($refundPoint > 0) {
$this->increaseInheritancePoint('previous', $refundPoint);
}
$this->mergeTotalInheritancePoint();
}
// 군주였으면 유지 이음
$officerLevel = $this->getVar('officer_level');
if($officerLevel == 12) {
if ($officerLevel == 12) {
nextRuler($this);
$this->setVar('officer_level', 1);
}
// 부대 처리
$troopLeaderID = $this->getVar('troop');
if($troopLeaderID == $generalID){
if ($troopLeaderID == $generalID) {
//부대장일 경우
// 모두 탈퇴
$db->update('general', [
'troop'=>0
'troop' => 0
], 'troop=%i', $troopLeaderID);
// 부대 삭제
$db->delete('troop', 'troop_leader=%i', $troopLeaderID);
}
if($sendDyingMessage){
if($dyingMessage){
if ($sendDyingMessage) {
if ($dyingMessage) {
$logger->pushGlobalActionLog($dyingMessage);
}
else{
} else {
$dyingMessageObj = new TextDecoration\DyingMessage($this);
$logger->pushGlobalActionLog($dyingMessageObj->getText());
}
@@ -587,9 +685,9 @@ class General implements iAction{
}
$db->update('select_pool', [
'general_id'=>null,
'owner'=>null,
'reserved_until'=>null,
'general_id' => null,
'owner' => null,
'reserved_until' => null,
], 'general_id=%i', $generalID);
$db->delete('general', 'no=%i', $generalID);
@@ -599,17 +697,18 @@ class General implements iAction{
$this->updatedVar = [];
$db->update('nation', [
'gennum'=>$db->sqleval('gennum - 1')
'gennum' => $db->sqleval('gennum - 1')
], 'nation=%i', $this->getVar('nation'));
}
function rebirth(){
function rebirth()
{
$logger = $this->getLogger();
$generalName = $this->getName();
$ownerID = $this->getVar('owner');
if($ownerID){
if ($ownerID) {
$this->mergeTotalInheritancePoint();
resetInheritanceUser($ownerID, true);
}
@@ -629,7 +728,7 @@ class General implements iAction{
$this->multiplyVar('dex4', 0.5);
$this->multiplyVar('dex5', 0.5);
foreach(array_keys(static::RANK_COLUMN) as $rankKey){
foreach (array_keys(static::RANK_COLUMN) as $rankKey) {
$this->setRankVar($rankKey, 0);
}
@@ -639,23 +738,24 @@ class General implements iAction{
$logger->pushGeneralHistoryLog('나이가 들어 은퇴하고, 자손에게 관직을 물려줌');
}
function increaseRankVar(string $key, int $value){
if(!key_exists($key, static::RANK_COLUMN)){
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key);
function increaseRankVar(string $key, int $value)
{
if (!key_exists($key, static::RANK_COLUMN)) {
throw new \InvalidArgumentException('올바르지 않은 인자 :' . $key);
}
if(key_exists($key, $this->rankVarSet)){
if (key_exists($key, $this->rankVarSet)) {
$this->rankVarSet[$key] += $value;
return;
}
if(key_exists($key, $this->rankVarRead)){
if (key_exists($key, $this->rankVarRead)) {
$this->rankVarSet[$key] = $this->rankVarRead[$key] + $value;
unset($this->rankVarRead[$key]);
return;
}
if(key_exists($key, $this->rankVarIncrease)){
if (key_exists($key, $this->rankVarIncrease)) {
$this->rankVarIncrease[$key] += $value;
return;
}
@@ -663,31 +763,32 @@ class General implements iAction{
$this->rankVarIncrease[$key] = $value;
}
function setRankVar(string $key, int $value){
if(!key_exists($key, static::RANK_COLUMN)){
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key);
function setRankVar(string $key, int $value)
{
if (!key_exists($key, static::RANK_COLUMN)) {
throw new \InvalidArgumentException('올바르지 않은 인자 :' . $key);
}
if(key_exists($key, $this->rankVarRead)){
if (key_exists($key, $this->rankVarRead)) {
unset($this->rankVarRead[$key]);
}
else if(key_exists($key, $this->rankVarIncrease)){
} else if (key_exists($key, $this->rankVarIncrease)) {
unset($this->rankVarIncrease[$key]);
}
$this->rankVarSet[$key]=$value;
$this->rankVarSet[$key] = $value;
}
function getRankVar(string $key):int{
if(!key_exists($key, static::RANK_COLUMN)){
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key);
function getRankVar(string $key): int
{
if (!key_exists($key, static::RANK_COLUMN)) {
throw new \InvalidArgumentException('올바르지 않은 인자 :' . $key);
}
if(key_exists($key, $this->rankVarSet)){
if (key_exists($key, $this->rankVarSet)) {
return $this->rankVarSet[$key];
}
if(!key_exists($key, $this->rankVarRead)){
throw new \RuntimeException('인자가 없음 : '.$key);
if (!key_exists($key, $this->rankVarRead)) {
throw new \RuntimeException('인자가 없음 : ' . $key);
}
return $this->rankVarRead[$key];
@@ -696,8 +797,9 @@ class General implements iAction{
/**
* @param \MeekroDB $db
*/
function applyDB($db):bool{
if($this->lastTurn && $this->getLastTurn() != $this->getResultTurn()){
function applyDB($db): bool
{
if ($this->lastTurn && $this->getLastTurn() != $this->getResultTurn()) {
$this->setVar('last_turn', $this->getResultTurn()->toJson());
}
$updateVals = $this->getUpdatedValues();
@@ -706,31 +808,31 @@ class General implements iAction{
$generalID = $this->getID();
$result = false;
if($updateVals){
if ($updateVals) {
$db->update('general', $updateVals, 'no=%i', $generalID);
$result = $result || $db->affectedRows() > 0;
if(key_exists('nation', $updateVals)){
if (key_exists('nation', $updateVals)) {
$db->update('rank_data', [
'nation_id'=>$updateVals['nation']
'nation_id' => $updateVals['nation']
], 'general_id = %i', $generalID);
$result = true;
}
$this->flushUpdateValues();
}
if($this->rankVarIncrease){
foreach($this->rankVarIncrease as $rankKey => $rankVal){
if ($this->rankVarIncrease) {
foreach ($this->rankVarIncrease as $rankKey => $rankVal) {
$db->update('rank_data', [
'value'=>$db->sqleval('value + %i', $rankVal)
'value' => $db->sqleval('value + %i', $rankVal)
], 'general_id = %i AND type = %s', $generalID, $rankKey);
}
$result = true;
}
if($this->rankVarSet){
foreach($this->rankVarSet as $rankKey => $rankVal){
if ($this->rankVarSet) {
foreach ($this->rankVarSet as $rankKey => $rankVal) {
$db->update('rank_data', [
'value'=>$rankVal
'value' => $rankVal
], 'general_id = %i AND type = %s', $generalID, $rankKey);
$this->rankVarRead[$rankKey] = $rankVal;
}
@@ -744,7 +846,8 @@ class General implements iAction{
return $result;
}
function checkStatChange():bool{
function checkStatChange(): bool
{
$logger = $this->getLogger();
$limit = GameConst::$upgradeLimit;
@@ -756,16 +859,15 @@ class General implements iAction{
$result = false;
foreach($table as [$statNickName, $statName]){
$statExpName = $statName.'_exp';
foreach ($table as [$statNickName, $statName]) {
$statExpName = $statName . '_exp';
if($this->getVar($statExpName) < 0){
if ($this->getVar($statExpName) < 0) {
$logger->pushGeneralActionLog("<R>{$statNickName}</>이 <C>1</> 떨어졌습니다!", ActionLogger::PLAIN);
$this->increaseVar($statExpName, $limit);
$this->increaseVar($statName, -1);
$result = true;
}
else if($this->getVar($statExpName) >= $limit){
} else if ($this->getVar($statExpName) >= $limit) {
$logger->pushGeneralActionLog("<S>{$statNickName}</>이 <C>1</> 올랐습니다!", ActionLogger::PLAIN);
$this->increaseVar($statExpName, -$limit);
$this->increaseVar($statName, 1);
@@ -776,18 +878,20 @@ class General implements iAction{
return $result;
}
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
public function getPreTurnExecuteTriggerList(General $general): ?GeneralTriggerCaller
{
$caller = new GeneralTriggerCaller();
foreach(array_merge([
foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
], $this->itemObjs) as $iObj){
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if(!$iObj){
if (!$iObj) {
continue;
}
/** @var iAction $iObj */
@@ -796,16 +900,18 @@ class General implements iAction{
return $caller;
}
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
foreach(array_merge([
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux = null): float
{
foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
], $this->itemObjs) as $iObj){
if(!$iObj){
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) {
continue;
}
/** @var iAction $iObj */
@@ -814,17 +920,19 @@ class General implements iAction{
return $value;
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
public function onCalcStat(General $general, string $statName, $value, $aux = null)
{
//xxx: $general?
foreach(array_merge([
foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
], $this->itemObjs) as $iObj){
if(!$iObj){
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) {
continue;
}
/** @var iAction $iObj */
@@ -833,16 +941,39 @@ class General implements iAction{
return $value;
}
public function onCalcStrategic(string $turnType, string $varType, $value){
foreach(array_merge([
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
//xxx: $general?
foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
], $this->itemObjs) as $iObj){
if(!$iObj){
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) {
continue;
}
/** @var iAction $iObj */
$value = $iObj->onCalcOpposeStat($this, $statName, $value, $aux);
}
return $value;
}
public function onCalcStrategic(string $turnType, string $varType, $value)
{
foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) {
continue;
}
/** @var iAction $iObj */
@@ -851,16 +982,18 @@ class General implements iAction{
return $value;
}
public function onCalcNationalIncome(string $type, $amount){
foreach(array_merge([
public function onCalcNationalIncome(string $type, $amount)
{
foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
], $this->itemObjs) as $iObj){
if(!$iObj){
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) {
continue;
}
/** @var iAction $iObj */
@@ -869,19 +1002,21 @@ class General implements iAction{
return $amount;
}
public function getWarPowerMultiplier(WarUnit $unit):array{
public function getWarPowerMultiplier(WarUnit $unit): array
{
//xxx:$unit
$att = 1;
$def = 1;
foreach(array_merge([
foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
], $this->itemObjs) as $iObj){
if(!$iObj){
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) {
continue;
}
/** @var iAction $iObj */
@@ -891,17 +1026,19 @@ class General implements iAction{
}
return [$att, $def];
}
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{
$caller = new WarUnitTriggerCaller();
foreach(array_merge([
foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
], $this->itemObjs) as $iObj){
if(!$iObj){
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) {
continue;
}
/** @var iAction $iObj */
@@ -910,7 +1047,8 @@ class General implements iAction{
return $caller;
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{
$caller = new WarUnitTriggerCaller(
new WarUnitTrigger\che_필살시도($unit),
new WarUnitTrigger\che_필살발동($unit),
@@ -920,15 +1058,16 @@ class General implements iAction{
new WarUnitTrigger\che_계략발동($unit),
new WarUnitTrigger\che_계략실패($unit)
);
foreach(array_merge([
foreach (array_merge([
$this->nationType,
$this->officerLevelObj,
$this->specialDomesticObj,
$this->specialWarObj,
$this->personalityObj,
$this->getCrewTypeObj(),
], $this->itemObjs) as $iObj){
if(!$iObj){
$this->inheritBuffObj,
], $this->itemObjs) as $iObj) {
if (!$iObj) {
continue;
}
/** @var iAction $iObj */
@@ -938,12 +1077,13 @@ class General implements iAction{
return $caller;
}
static public function mergeQueryColumn(?array $reqColumns=null, int $constructMode=2):array{
static public function mergeQueryColumn(?array $reqColumns = null, int $constructMode = 2): array
{
$minimumColumn = ['no', 'name', 'city', 'nation', 'officer_level', 'officer_city'];
$defaultEventColumn = [
'no', 'name', 'owner', 'city', 'nation', 'officer_level', 'officer_city',
'special', 'special2', 'personal',
'horse', 'weapon', 'book', 'item', 'last_turn'
'horse', 'weapon', 'book', 'item', 'last_turn', 'aux',
];
$fullColumn = [
'no', 'name', 'owner', 'owner_name', 'picture', 'imgsvr', 'nation', 'city', 'troop', 'injury', 'affinity',
@@ -956,22 +1096,21 @@ class General implements iAction{
'specage', 'specage2', 'con', 'connect', 'aux', 'lastrefresh',
];
if($reqColumns === null){
if ($reqColumns === null) {
return [$fullColumn, array_keys(static::RANK_COLUMN)];
}
$rankColumn = [];
$subColumn = [];
foreach($reqColumns as $column){
if(key_exists($column, static::RANK_COLUMN)){
foreach ($reqColumns as $column) {
if (key_exists($column, static::RANK_COLUMN)) {
$rankColumn[] = $column;
}
else{
} else {
$subColumn[] = $column;
}
}
if($constructMode > 1){
if ($constructMode > 1) {
return [array_unique(array_merge($defaultEventColumn, $subColumn)), $rankColumn];
}
@@ -985,31 +1124,30 @@ class General implements iAction{
* @return \sammo\General[]
* @throws MustNotBeReachedException
*/
static public function createGeneralObjListFromDB(?array $generalIDList, ?array $column=null, int $constructMode=2):array{
if($generalIDList === []){
static public function createGeneralObjListFromDB(?array $generalIDList, ?array $column = null, int $constructMode = 2): array
{
if ($generalIDList === []) {
return [];
}
$db = DB::db();
if($constructMode > 0){
if ($constructMode > 0) {
$gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
}
else{
} else {
$year = null;
$month = null;
}
[$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode);
if($generalIDList === null){
if ($generalIDList === null) {
$rawGenerals = Util::convertArrayToDict(
$db->query('SELECT %l FROM general WHERE 1', Util::formatListOfBackticks($column)),
'no'
);
$generalIDList = array_keys($rawGenerals);
}
else{
} else {
$rawGenerals = Util::convertArrayToDict(
$db->query('SELECT %l FROM general WHERE no IN %li', Util::formatListOfBackticks($column), $generalIDList),
'no'
@@ -1018,14 +1156,14 @@ class General implements iAction{
$rawRanks = [];
if($rankColumn){
if ($rankColumn) {
$rawValue = $db->queryAllLists(
'SELECT `general_id`, `type`, `value` FROM rank_data WHERE general_id IN %li AND `type` IN %ls',
$generalIDList,
$rankColumn
);
foreach($rawValue as [$generalID, $rankType, $rankValue]){
if(!key_exists($generalID, $rawRanks)){
foreach ($rawValue as [$generalID, $rankType, $rankValue]) {
if (!key_exists($generalID, $rawRanks)) {
$rawRanks[$generalID] = [];
}
$rawRanks[$generalID][$rankType] = $rankValue;
@@ -1033,27 +1171,27 @@ class General implements iAction{
}
$result = [];
foreach($generalIDList as $generalID){
if(!key_exists($generalID, $rawGenerals)){
foreach ($generalIDList as $generalID) {
if (!key_exists($generalID, $rawGenerals)) {
$result[$generalID] = new DummyGeneral($constructMode > 0);
continue;
}
if(key_exists($generalID, $rawRanks) && count($rawRanks[$generalID]??[]) !== count($rankColumn)){
throw new \RuntimeException('column의 수가 일치하지 않음 : '.$generalID);
if (key_exists($generalID, $rawRanks) && count($rawRanks[$generalID] ?? []) !== count($rankColumn)) {
throw new \RuntimeException('column의 수가 일치하지 않음 : ' . $generalID);
}
$result[$generalID] = new static($rawGenerals[$generalID], $rawRanks[$generalID]??null, null, null, $year, $month, $constructMode > 1);
$result[$generalID] = new static($rawGenerals[$generalID], $rawRanks[$generalID] ?? null, null, null, $year, $month, $constructMode > 1);
}
return $result;
}
static public function createGeneralObjFromDB(int $generalID, ?array $column=null, int $constructMode=2):self{
static public function createGeneralObjFromDB(int $generalID, ?array $column = null, int $constructMode = 2): self
{
$db = DB::db();
if($constructMode > 0){
if ($constructMode > 0) {
$gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
}
else{
} else {
$year = null;
$month = null;
}
@@ -1061,14 +1199,14 @@ class General implements iAction{
[$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode);
$rawGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no = %i', Util::formatListOfBackticks($column), $generalID);
if(!$rawGeneral){
if (!$rawGeneral) {
return new DummyGeneral($constructMode > 0);
}
$rawRankValues = [];
if($rankColumn){
if ($rankColumn) {
$rawValue = $db->queryAllLists('SELECT `type`, `value` FROM rank_data WHERE general_id = %i AND `type` IN %ls', $generalID, $rankColumn);
foreach($rawValue as [$rankType, $rankValue]){
foreach ($rawValue as [$rankType, $rankValue]) {
$rawRankValues[$rankType] = $rankValue;
}
}
@@ -1085,21 +1223,22 @@ class General implements iAction{
* @param array $env
* @return GeneralCommand[]
*/
static public function getReservedTurnByGeneralList(array $generalList, int $turnIdx, array $env){
if(!$generalList){
static public function getReservedTurnByGeneralList(array $generalList, int $turnIdx, array $env)
{
if (!$generalList) {
return [];
}
$generalIDList = array_map(function(General $general){
$generalIDList = array_map(function (General $general) {
return $general->getID();
}, $generalList);
$db = DB::db();
$result = [];
$rawCmds = Util::convertArrayToDict($db->query('SELECT * FROM general_turn WHERE general_id IN %li AND turn_idx = %i', $generalIDList, $turnIdx), 'general_id');
foreach($generalList as $general){
foreach ($generalList as $general) {
$generalID = $general->getID();
if(!key_exists($generalID, $rawCmds)){
if (!key_exists($generalID, $rawCmds)) {
$result[$generalID] = buildGeneralCommandClass(null, $general, $env);
continue;
}
@@ -1116,21 +1255,22 @@ class General implements iAction{
* @param array $env
* @return GeneralCommand[][]
*/
static public function getReservedTurnListByGeneralList(array $generalList, int $turnIdxFrom, int $turnIdxTo, array $env){
static public function getReservedTurnListByGeneralList(array $generalList, int $turnIdxFrom, int $turnIdxTo, array $env)
{
//XXX: static인데 return값이 General이 아니라고?? GeneralCommandHelper같은게 있어야하지 않을까?
if(!$generalList){
if (!$generalList) {
return [];
}
if($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn){
throw new \OutOfRangeException('$turnIdxFrom 범위 초과'.$turnIdxFrom);
if ($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn) {
throw new \OutOfRangeException('$turnIdxFrom 범위 초과' . $turnIdxFrom);
}
if($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo){
throw new \OutOfRangeException('$turnIdxTo 범위 초과'.$turnIdxTo);
if ($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo) {
throw new \OutOfRangeException('$turnIdxTo 범위 초과' . $turnIdxTo);
}
$generalIDList = array_map(function(General $general){
$generalIDList = array_map(function (General $general) {
return $general->getID();
}, $generalList);
@@ -1138,26 +1278,26 @@ class General implements iAction{
$rawCmds = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id IN %i AND %i <= turn_idx AND turn_idx < %i ORDER BY general_id ASC, turn_idx ASC', $generalIDList, $turnIdxFrom, $turnIdxTo);
$orderedRawCmds = [];
foreach($rawCmds as $rawCmd){
foreach ($rawCmds as $rawCmd) {
$generalID = $rawCmd['general_id'];
$turnIdx = $rawCmd['turn_idx'];
if(!key_exists($generalID, $orderedRawCmds)){
if (!key_exists($generalID, $orderedRawCmds)) {
$orderedRawCmds[$generalID] = [];
}
$orderedRawCmds[$generalID][$turnIdx] = $rawCmd;
}
$result = [];
foreach($generalList as $general){
foreach ($generalList as $general) {
$generalID = $general->getID();
$result[$generalID] = [];
if(!key_exists($generalID, $orderedRawCmds)){
foreach(Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx){
if (!key_exists($generalID, $orderedRawCmds)) {
foreach (Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx) {
$result[$generalID][$turnIdx] = buildGeneralCommandClass(null, $general, $env);
}
continue;
}
foreach($orderedRawCmds[$generalID] as $turnIdx=>$rawCmd){
foreach ($orderedRawCmds[$generalID] as $turnIdx => $rawCmd) {
$result[$generalID][$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $general, $env, Json::decode($rawCmd['arg']));
}
}
@@ -1167,109 +1307,113 @@ class General implements iAction{
/**
* @return int|float
*/
public function getInheritancePoint(string $key, &$aux=null, bool $forceCalc=false){
$inheritType = static::INHERITANCE_KEY[$key]??null;
if($inheritType === null){
public function getInheritancePoint(string $key, &$aux = null, bool $forceCalc = false)
{
$inheritType = static::INHERITANCE_KEY[$key] ?? null;
if ($inheritType === null) {
throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
}
$ownerID = $this->getVar('owner');
if(!$ownerID){
if (!$ownerID) {
return 0;
}
if($this->getVar('npc') != 0){
if ($this->getVar('npc') != 0) {
return 0;
}
[$storeType, $multiplier, ] = $inheritType;
[$storeType, $multiplier,] = $inheritType;
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
if($storeType === true || ($gameStor->isunited != 0 && !$forceCalc)){
if ($storeType === true || ($gameStor->isunited != 0 && !$forceCalc)) {
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
[$value, $aux] = $inheritStor->getValue($key);
return $value;
}
if(is_array($storeType)){
if (is_array($storeType)) {
[$storSubType, $storSubKey] = $storeType;
if($storSubType === 'rank'){
if ($storSubType === 'rank') {
return $this->getRankVar($storSubKey) * $multiplier;
}
if($storSubType === 'raw'){
if ($storSubType === 'raw') {
return $this->getVar($storSubKey) * $multiplier;
}
if($storSubType === 'aux'){
return ($this->getAuxVar($storSubKey)??0) * $multiplier;
if ($storSubType === 'aux') {
return ($this->getAuxVar($storSubKey) ?? 0) * $multiplier;
}
throw new \InvalidArgumentException("{$storSubType}은 참조 할 수 없는 유산 세부키임");
}
if($storeType !== false){
if ($storeType !== false) {
throw new \InvalidArgumentException("{$storeType}은 올바르지 않은 유산 키임");
}
$extractFn = function(){ return [0, null];};
switch($key){
case 'dex':
$extractFn = function() use ($multiplier){
$totalDex = 0;
foreach(array_keys(GameUnitConst::allType()) as $armType){
$totalDex += $this->getVar("dex{$armType}");
}
return [$totalDex * $multiplier, null];
};
break;
case 'betting':
$extractFn = function() use ($multiplier){
$betWin = $this->getRankVar('betwin');
$betWinRate = $this->getRankVar('betwingold')/max(1, $this->getRankVar('betgold'));
$extractFn = function () {
return [0, null];
};
switch ($key) {
case 'dex':
$extractFn = function () use ($multiplier) {
$totalDex = 0;
foreach (array_keys(GameUnitConst::allType()) as $armType) {
$totalDex += $this->getVar("dex{$armType}");
}
return [$totalDex * $multiplier, null];
};
break;
case 'betting':
$extractFn = function () use ($multiplier) {
$betWin = $this->getRankVar('betwin');
$betWinRate = $this->getRankVar('betwingold') / max(1, $this->getRankVar('betgold'));
return [$betWin * $multiplier * pow($betWinRate, 2), null];
};
break;
case 'max_belong':
$extractFn = function() use ($multiplier){
$maxBelong = max($this->getVar('belong'), $this->getAuxVar('max_belong')??0);
return [$maxBelong * $multiplier, null];
};
break;
default:
throw new \InvalidArgumentException("{$key}는 유산 추출기를 보유하고 있지 않음");
return [$betWin * $multiplier * pow($betWinRate, 2), null];
};
break;
case 'max_belong':
$extractFn = function () use ($multiplier) {
$maxBelong = max($this->getVar('belong'), $this->getAuxVar('max_belong') ?? 0);
return [$maxBelong * $multiplier, null];
};
break;
default:
throw new \InvalidArgumentException("{$key}는 유산 추출기를 보유하고 있지 않음");
}
[$value, $aux] = ($extractFn)();
return $value;
}
public function setInheritancePoint(string $key, $value, $aux=null){
if(!is_int($value) && !is_float($value)){
public function setInheritancePoint(string $key, $value, $aux = null)
{
if (!is_int($value) && !is_float($value)) {
throw new \InvalidArgumentException("{$value}는 숫자가 아님");
}
$inheritType = static::INHERITANCE_KEY[$key]??null;
if($inheritType === null){
$inheritType = static::INHERITANCE_KEY[$key] ?? null;
if ($inheritType === null) {
throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
}
[$storeType, $multiplier, ] = $inheritType;
if($storeType !== true){
[$storeType, $multiplier,] = $inheritType;
if ($storeType !== true) {
throw new \InvalidArgumentException("{$key}는 직접 저장형 유산 포인트가 아님");
}
if($multiplier != 1 && $value != 0){
if ($multiplier != 1 && $value != 0) {
throw new \InvalidArgumentException("{$key}는 1:1 유산 포인트가 아님");
}
$ownerID = $this->getVar('owner');
if(!$ownerID){
if (!$ownerID) {
return;
}
if($this->getVar('npc') != 0){
if ($this->getVar('npc') != 0) {
return;
}
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
if($gameStor->isunited != 0){
if ($gameStor->isunited != 0) {
return;
}
@@ -1277,39 +1421,40 @@ class General implements iAction{
$inheritStor->setValue($key, [$value, $aux]);
}
public function increaseInheritancePoint(string $key, $value, $aux=null){
if(!is_int($value) && !is_float($value)){
public function increaseInheritancePoint(string $key, $value, $aux = null)
{
if (!is_int($value) && !is_float($value)) {
throw new \InvalidArgumentException("{$value}는 숫자가 아님");
}
$inheritType = static::INHERITANCE_KEY[$key]??null;
if($inheritType === null){
$inheritType = static::INHERITANCE_KEY[$key] ?? null;
if ($inheritType === null) {
throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
}
[$storeType, $multiplier, ] = $inheritType;
if($storeType !== true){
[$storeType, $multiplier,] = $inheritType;
if ($storeType !== true) {
throw new \InvalidArgumentException("{$key}는 직접 저장형 유산 포인트가 아님");
}
$ownerID = $this->getVar('owner');
if(!$ownerID){
if (!$ownerID) {
return;
}
if($this->getVar('npc') != 0){
if ($this->getVar('npc') != 0) {
return;
}
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
if($gameStor->isunited != 0){
if ($gameStor->isunited != 0) {
return;
}
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
[$oldValue, $oldAux] = $inheritStor->getValue($key)??[0, null];
[$oldValue, $oldAux] = $inheritStor->getValue($key) ?? [0, null];
if($oldAux !== $aux){
if ($oldAux !== $aux) {
$oldValue = 0;
}
@@ -1317,22 +1462,23 @@ class General implements iAction{
$inheritStor->setValue($key, [$newValue, $aux]);
}
public function mergeTotalInheritancePoint(){
public function mergeTotalInheritancePoint()
{
$ownerID = $this->getVar('owner');
if(!$ownerID){
if (!$ownerID) {
return;
}
if($this->getVar('npc') != 0){
if ($this->getVar('npc') != 0) {
return;
}
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
$inheritStor->cacheAll();
foreach(static::INHERITANCE_KEY as $key=>[$storType, ,]){
foreach (static::INHERITANCE_KEY as $key => [$storType,,]) {
$aux = null;
$point = $this->getInheritancePoint($key, $aux, true);
if($storType === true){
if ($storType === true) {
continue;
}
$inheritStor->setValue($key, [$point, $aux]);
@@ -1345,4 +1491,4 @@ class General implements iAction{
$month = $gameStor->month;
$oldInheritStor->setValue("{$serverID}_{$ownerID}_{$this->getID()}_{$year}_{$month}", $inheritStor->getAll(true));
}
}
}
+2 -2
View File
@@ -10,7 +10,7 @@ trait LazyVarUpdater{
function getRaw(bool $extractAux=false):array{
if($extractAux){
$this->getAuxVar('');
}
return $this->raw;
}
@@ -58,7 +58,7 @@ trait LazyVarUpdater{
}
if($var === null){
unset($this->auxVar[$key]);
unset($this->raw['auxVar'][$key]);
$this->auxUpdated = true;
return;
}
+1 -1
View File
@@ -681,7 +681,7 @@ class GeneralBuilder{
'turntime'=>$turntime,
'killturn'=>$killturn,
'age'=>$age,
'belong'=>1,
'belong'=>0,
'personal'=>$this->ego,
'special'=>$this->specialDomestic,
'specage'=>$this->specAge,
+130
View File
@@ -0,0 +1,130 @@
<?php
namespace sammo;
class TriggerInheritBuff implements iAction
{
use DefaultAction;
//TODO Ratio와 Prob 혼용 중지
const WAR_AVOID_RATIO = 'warAvoidRatio';
const WAR_CRITICAL_RATIO = 'warCriticalRatio';
const WAR_MAGIC_TRIAL_PROB = 'warMagicTrialProb';
const DOMESTIC_SUCCESS_PROB = 'domesticSuccessProb';
const DOMESTIC_FAIL_PROB = 'domesticFailProb';
const OPPOSE_WAR_AVOID_RATIO = 'warAvoidRatioOppose';
const OPPOSE_WAR_CRITICAL_RATIO = 'warCriticalRatioOppose';
const OPPOSE_WAR_MAGIC_TRIAL_PROB = 'warMagicTrialProbOppose';
const MAX_STEP = 5;
const BUFF_KEY_MAP = [
self::WAR_AVOID_RATIO => 'warAvoidRatio',
self::WAR_CRITICAL_RATIO => 'warCriticalRatio',
self::WAR_MAGIC_TRIAL_PROB => 'warMagicTrialProb',
self::DOMESTIC_SUCCESS_PROB => 'success',
self::DOMESTIC_FAIL_PROB => 'fail',
self::OPPOSE_WAR_AVOID_RATIO => 'warAvoidRatio',
self::OPPOSE_WAR_CRITICAL_RATIO => 'warCriticalRatio',
self::OPPOSE_WAR_MAGIC_TRIAL_PROB => 'warMagicTrialProb',
];
const CALC_DOMESTIC = [
self::BUFF_KEY_MAP[self::DOMESTIC_SUCCESS_PROB] => [self::DOMESTIC_SUCCESS_PROB, 0.01],
self::BUFF_KEY_MAP[self::DOMESTIC_FAIL_PROB] => [self::DOMESTIC_FAIL_PROB, -0.01],
];
const CALC_STAT = [
self::BUFF_KEY_MAP[self::WAR_AVOID_RATIO] => [self::WAR_AVOID_RATIO, 0.01],
self::BUFF_KEY_MAP[self::WAR_CRITICAL_RATIO] => [self::WAR_CRITICAL_RATIO, 0.01],
self::BUFF_KEY_MAP[self::WAR_MAGIC_TRIAL_PROB] => [self::WAR_MAGIC_TRIAL_PROB, 0.01],
];
const CALC_OPPOSE_STAT = [
self::BUFF_KEY_MAP[self::OPPOSE_WAR_AVOID_RATIO] => [self::OPPOSE_WAR_AVOID_RATIO, -0.01],
self::BUFF_KEY_MAP[self::OPPOSE_WAR_CRITICAL_RATIO] => [self::OPPOSE_WAR_CRITICAL_RATIO, -0.01],
self::BUFF_KEY_MAP[self::OPPOSE_WAR_MAGIC_TRIAL_PROB] => [self::OPPOSE_WAR_MAGIC_TRIAL_PROB, -0.01],
];
const BUFF_KEY_TEXT = [
self::WAR_AVOID_RATIO => '회피 확률 증가',
self::WAR_CRITICAL_RATIO => '필살 확률 증가',
self::WAR_MAGIC_TRIAL_PROB => '전투계략 시도 확률 증가',
self::DOMESTIC_SUCCESS_PROB => '내정 성공률 증가',
self::DOMESTIC_FAIL_PROB => '내정 실패율 감소',
self::OPPOSE_WAR_AVOID_RATIO => '상대 회피 확률 감소',
self::OPPOSE_WAR_CRITICAL_RATIO => '상대 필살 확률 감소',
self::OPPOSE_WAR_MAGIC_TRIAL_PROB => '상대 전투계략 시도 확률 감소',
];
const DOMESTIC_TARGET = [
'상업' => 1,
'농업' => 1,
'치안' => 1,
'성벽' => 1,
'수비' => 1,
'민심' => 1,
'인구' => 1,
'기술' => 1,
];
protected array $inheritBuffList;
public function __construct(array $inheritBuffList)
{
$this->inheritBuffList = $inheritBuffList;
}
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux = null): float
{
if (count($this->inheritBuffList) == 0) {
return $value;
}
if (!key_exists($turnType, self::DOMESTIC_TARGET)) {
return $value;
}
if(!key_exists($varType, static::CALC_DOMESTIC)){
return $value;
}
[$iKey, $coeff] = static::CALC_DOMESTIC[$varType];
if(!key_exists($iKey, $this->inheritBuffList)){
return $value;
}
return $value + $coeff * $this->inheritBuffList[$iKey];
}
public function onCalcStat(General $general, string $statName, $value, $aux = null)
{
if (count($this->inheritBuffList) == 0) {
return $value;
}
if(!key_exists($statName, static::CALC_STAT)){
return $value;
}
[$iKey, $coeff] = static::CALC_STAT[$statName];
if(!key_exists($iKey, $this->inheritBuffList)){
return $value;
}
return $value + $coeff * $this->inheritBuffList[$iKey];
}
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
if (count($this->inheritBuffList) == 0) {
return $value;
}
if(!key_exists($statName, static::CALC_OPPOSE_STAT)){
return $value;
}
[$iKey, $coeff] = static::CALC_OPPOSE_STAT[$statName];
if(!key_exists($iKey, $this->inheritBuffList)){
return $value;
}
return $value + $coeff * $this->inheritBuffList[$iKey];
}
}
+94 -86
View File
@@ -1,7 +1,9 @@
<?php
namespace sammo;
use \Symfony\Component\Lock;
class TurnExecutionHelper
{
/** @var General*/
@@ -17,16 +19,19 @@ class TurnExecutionHelper
$this->applyDB();
}
public function applyDB(){
public function applyDB()
{
$db = DB::db();
$this->generalObj->applyDB($db);
}
public function getGeneral():General{
public function getGeneral(): General
{
return $this->generalObj;
}
public function preprocessCommand(array $env){
public function preprocessCommand(array $env)
{
$general = $this->getGeneral();
$caller = $general->getPreTurnExecuteTriggerList($general);
$caller->merge(new GeneralTriggerCaller(
@@ -37,37 +42,37 @@ class TurnExecutionHelper
$caller->fire($env);
}
public function processBlocked():bool{
public function processBlocked(): bool
{
$general = $this->getGeneral();
$blocked = $general->getVar('block');
if($blocked < 2){
if ($blocked < 2) {
return false;
}
$date = $general->getTurnTime($general::TURNTIME_HM);
$logger = $general->getLogger();
if($blocked == 2){
if ($blocked == 2) {
$general->increaseVarWithLimit('killturn', -1, 0);
$logger->pushGeneralActionLog("현재 멀티, 또는 비매너로 인한<R>블럭</> 대상자입니다. <1>$date</>");
}
else if($blocked == 3){
} else if ($blocked == 3) {
$general->increaseVarWithLimit('killturn', -1, 0);
$logger->pushGeneralActionLog("현재 악성유저로 분류되어 <R>블럭</> 대상자입니다. <1>$date</>");
}
else{
} else {
//Hmm?
return false;
}
return true;
}
public function processNationCommand(Command\NationCommand $commandObj):LastTurn{
public function processNationCommand(Command\NationCommand $commandObj): LastTurn
{
$general = $this->getGeneral();
while(true){
if(!$commandObj->hasFullConditionMet()){
while (true) {
if (!$commandObj->hasFullConditionMet()) {
$date = $general->getTurnTime($general::TURNTIME_HM);
$failString = $commandObj->getFailString();
$text = "{$failString} <1>{$date}</>";
@@ -75,7 +80,7 @@ class TurnExecutionHelper
break;
}
if(!$commandObj->addTermStack()){
if (!$commandObj->addTermStack()) {
$date = $general->getTurnTime($general::TURNTIME_HM);
$termString = $commandObj->getTermString();
$text = "{$termString} <1>{$date}</>";
@@ -84,14 +89,14 @@ class TurnExecutionHelper
}
$result = $commandObj->run();
if($result){
if ($result) {
$commandObj->setNextAvailable();
break;
}
$alt = $commandObj->getAlternativeCommand();
if($alt === null){
if ($alt === null) {
break;
}
$commandObj = $alt;
@@ -101,7 +106,8 @@ class TurnExecutionHelper
return $commandObj->getResultTurn();
}
public function processCommand(Command\GeneralCommand $commandObj, bool $autorunMode){
public function processCommand(Command\GeneralCommand $commandObj, bool $autorunMode)
{
$general = $this->getGeneral();
@@ -109,16 +115,16 @@ class TurnExecutionHelper
$gameStor = KVStorage::getStorage($db, 'game_env');
$commandClassName = $commandObj->getName();
while(true){
if(!$commandObj->hasFullConditionMet()){
while (true) {
if (!$commandObj->hasFullConditionMet()) {
$date = $general->getTurnTime($general::TURNTIME_HM);
$failString = $commandObj->getFailString();
$text = "{$failString} <1>{$date}</>";
$general->getLogger()->pushGeneralActionLog($text);
break;
}
if(!$commandObj->addTermStack()){
if (!$commandObj->addTermStack()) {
$date = $general->getTurnTime($general::TURNTIME_HM);
$termString = $commandObj->getTermString();
$text = "{$termString} <1>{$date}</>";
@@ -127,43 +133,40 @@ class TurnExecutionHelper
}
$result = $commandObj->run();
if($result){
if ($result) {
$commandObj->setNextAvailable();
break;
}
$alt = $commandObj->getAlternativeCommand();
if($alt === null){
if ($alt === null) {
break;
}
$commandObj = $alt;
$commandClassName = $alt->getName();
}
$general->clearActivatedSkill();
$killTurn = $gameStor->killturn;
if($general->getNPCType() >= 2){
if ($general->getNPCType() >= 2) {
$general->increaseVarWithLimit('killturn', -1);
}
else if($general->getVar('killturn') > $killTurn){
} else if ($general->getVar('killturn') > $killTurn) {
$general->increaseVarWithLimit('killturn', -1);
}
else if($autorunMode){
} else if ($autorunMode) {
$general->increaseVarWithLimit('killturn', -1);
}
else if($commandClassName == '휴식'){
} else if ($commandClassName == '휴식') {
$general->increaseVarWithLimit('killturn', -1);
}
else{
} else {
$general->setVar('killturn', $killTurn);
}
return $commandObj->getResultTurn();
}
function updateTurnTime(){
function updateTurnTime()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -175,13 +178,13 @@ class TurnExecutionHelper
$generalName = $general->getName();
// 삭턴장수 삭제처리
if($general->getVar('killturn') <= 0){
if ($general->getVar('killturn') <= 0) {
// npc유저 삭턴시 npc로 전환
if($general->getNPCType() == 1 && $general->getVar('deadyear') > $gameStor->year){
if ($general->getNPCType() == 1 && $general->getVar('deadyear') > $gameStor->year) {
$ownerName = $general->getVar('owner_name');
$josaYi = JosaUtil::pick($ownerName, '이');
$logger->pushGlobalActionLog("{$ownerName}</>{$josaYi} <Y>{$generalName}</>의 육체에서 <S>유체이탈</>합니다!");
$general->setVar('killturn', ($general->getVar('deadyear') - $gameStor->year) * 12);
@@ -189,8 +192,7 @@ class TurnExecutionHelper
$general->setVar('owner', 0);
$general->setVar('defence_train', 80);
$general->setVar('owner_name', null);
}
else{
} else {
$general->applyDB($db);
storeOldGeneral($generalID, $gameStor->year, $gameStor->month);
$general->kill($db);
@@ -199,8 +201,8 @@ class TurnExecutionHelper
}
//은퇴
if($general->getVar('age') >= GameConst::$retirementYear && $general->getNPCType() == 0) {
if($gameStor->isunited == 0) {
if ($general->getVar('age') >= GameConst::$retirementYear && $general->getNPCType() == 0) {
if ($gameStor->isunited == 0) {
$general->applyDB($db);
CheckHall($generalID);
}
@@ -210,11 +212,11 @@ class TurnExecutionHelper
$turntime = addTurn($general->getTurnTime(), $gameStor->turnterm);
$general->setVar('turntime', $turntime);
}
static public function executeGeneralCommandUntil(string $date, \DateTimeInterface $limitActionTime, int $year, int $month){
static public function executeGeneralCommandUntil(string $date, \DateTimeInterface $limitActionTime, int $year, int $month)
{
$db = DB::db();
$generalsTodo = $db->query(
'SELECT no,name,turntime,killturn,block,npc,deadyear FROM general WHERE turntime < %s ORDER BY turntime ASC, `no` ASC',
@@ -226,9 +228,9 @@ class TurnExecutionHelper
$gameStor = KVStorage::getStorage($db, 'game_env');
$autorun_user = $gameStor->autorun_user;
foreach($generalsTodo as $rawGeneral){
foreach ($generalsTodo as $rawGeneral) {
$currActionTime = new \DateTimeImmutable();
if($currActionTime > $limitActionTime){
if ($currActionTime > $limitActionTime) {
return [true, $currentTurn];
}
@@ -238,7 +240,7 @@ class TurnExecutionHelper
$env = $gameStor->getAll(true);
$hasNationTurn = false;
if($general->getVar('nation') != 0 && $general->getVar('officer_level') >= 5){
if ($general->getVar('nation') != 0 && $general->getVar('officer_level') >= 5) {
$nationStor = KVStorage::getStorage($db, $general->getNationID(), 'nation_env');
$lastNationTurnKey = "turn_last_{$general->getVar('officer_level')}";
//수뇌 몇 없는데 매번 left join 하는건 낭비인것 같다.
@@ -246,10 +248,10 @@ class TurnExecutionHelper
'SELECT action, arg FROM nation_turn WHERE nation_id = %i AND officer_level = %i AND turn_idx =0',
$general->getVar('nation'),
$general->getVar('officer_level')
)??[];
) ?? [];
$hasNationTurn = true;
$nationCommand = $rawNationTurn['action']??null;
$nationArg = Json::decode($rawNationTurn['arg']??null);
$nationCommand = $rawNationTurn['action'] ?? null;
$nationArg = Json::decode($rawNationTurn['arg'] ?? null);
$lastNationTurn = LastTurn::fromRaw($nationStor->getValue($lastNationTurnKey));
$nationCommandObj = buildNationCommandClass($nationCommand, $general, $env, $lastNationTurn, $nationArg);
}
@@ -260,16 +262,15 @@ class TurnExecutionHelper
$general->increaseInheritancePoint('lived_month', 1);
$turnObj->preprocessCommand($env);
$generalCommandObj = $general->getReservedTurn(0, $env);
if($general->getNPCType() >= 2 || ($autorun_user['limit_minutes']??false)){
if ($general->getNPCType() >= 2 || ($autorun_user['limit_minutes'] ?? false)) {
$ai = new GeneralAI($turnObj->getGeneral());
}
if(!$turnObj->processBlocked()){
if($hasNationTurn){
if($ai && ($general->getAuxVar('use_auto_nation_turn')??1)){
if (!$turnObj->processBlocked()) {
if ($hasNationTurn) {
if ($ai && ($general->getAuxVar('use_auto_nation_turn') ?? 1)) {
$nationCommandObj = $ai->chooseNationTurn($nationCommandObj);
$cityName = CityConst::byID($general->getCityID())->name;
LogText("NationTurn", "General, {$general->getName()}, {$general->getID()}, {$cityName}, {$general->getStaticNation()['name']}, {$nationCommandObj->getBrief()}, {$nationCommandObj->reason}, ");
@@ -278,18 +279,21 @@ class TurnExecutionHelper
$nationCommandObj
);
$nationStor->setValue($lastNationTurnKey, $resultNationTurn->toRaw());
$general->setRawCity(null);
}
if($ai){
$generalCommandObj = $general->getReservedTurn(0, $env);
if ($ai) {
$newGeneralCommandObj = $ai->chooseGeneralTurn($generalCommandObj); // npc AI 처리
if($generalCommandObj !== $newGeneralCommandObj){
if ($generalCommandObj !== $newGeneralCommandObj) {
$autorunMode = true;
$generalCommandObj = $newGeneralCommandObj;
}
$cityName = CityConst::byID($general->getCityID())->name;
LogText("turn", "General, {$general->getName()}, {$general->getID()}, {$cityName}, {$general->getStaticNation()['name']}, {$generalCommandObj->getBrief()}, {$generalCommandObj->reason}, ");
}
$turnObj->processCommand($generalCommandObj, $autorunMode);
}
pullNationCommand($general->getVar('nation'), $general->getVar('officer_level'));
@@ -300,26 +304,25 @@ class TurnExecutionHelper
$turnObj->updateTurnTime();
$turnObj->applyDB();
}
return [false, $currentTurn];
}
static public function executeAllCommand(){
static public function executeAllCommand()
{
//if(!timeover()) { return; }
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if(TimeUtil::now(true) < $gameStor->turntime){
if (TimeUtil::now(true) < $gameStor->turntime) {
//턴 시각 이전이면 아무것도 하지 않음
return true;
}
if(!tryLock()){
if (!tryLock()) {
return;
}
@@ -342,13 +345,12 @@ class TurnExecutionHelper
$nextTurn = addTurn($prevTurn, $gameStor->turnterm);
$maxActionTime = Util::toInt(ini_get('max_execution_time'));
if($maxActionTime == 0){
if ($maxActionTime == 0) {
$maxActionTime = 60;
}
else {
} else {
$maxActionTime = max($maxActionTime * 2 / 3, $maxActionTime - 10);
}
$limitActionTime = (new \DateTimeImmutable())->add(TimeUtil::secondsToDateInterval($maxActionTime));
// 현재 턴 이전 월턴까지 모두처리.
@@ -356,23 +358,26 @@ class TurnExecutionHelper
while ($nextTurn <= $date) {
[$executionOver, $currentTurn] = static::executeGeneralCommandUntil(
$nextTurn, $limitActionTime, $gameStor->year, $gameStor->month
$nextTurn,
$limitActionTime,
$gameStor->year,
$gameStor->month
);
// 트래픽 업데이트
updateTraffic();
if($executionOver){
if($currentTurn !== null){
if ($executionOver) {
if ($currentTurn !== null) {
$gameStor->turntime = $currentTurn;
}
unlock();
return;
}
// 1달마다 처리하는 것들, 벌점 감소 및 건국,전턴,합병 -1, 군량 소모
if(!preUpdateMonthly()){
if (!preUpdateMonthly()) {
$gameStor->resetCache(true);
unlock();
throw new \RuntimeException('preUpdateMonthly() 처리 에러');
@@ -383,7 +388,7 @@ class TurnExecutionHelper
$logger = new ActionLogger(0, 0, $gameStor->year, $gameStor->month, false);
// 분기계산. 장수들 턴보다 먼저 있다면 먼저처리
if($gameStor->month == 1) {
if ($gameStor->month == 1) {
processSpring();
processGoldIncome();
updateYearly();
@@ -394,16 +399,16 @@ class TurnExecutionHelper
// 새해 알림
$logger->pushGlobalActionLog("<C>{$gameStor->year}</>년이 되었습니다.");
$logger->flush(); //TODO: globalAction류는 전역에서 관리하는것이 좋을 듯.
} elseif($gameStor->month == 4) {
} elseif ($gameStor->month == 4) {
updateQuaterly();
disaster();
} elseif($gameStor->month == 7) {
} elseif ($gameStor->month == 7) {
processFall();
processRiceIncome();
updateQuaterly();
disaster();
tradeRate();
} elseif($gameStor->month == 10) {
} elseif ($gameStor->month == 10) {
updateQuaterly();
disaster();
}
@@ -411,7 +416,7 @@ class TurnExecutionHelper
// 이벤트 핸들러 동작
$e_env = null;
foreach (DB::db()->query('SELECT * from event') as $rawEvent) {
if($e_env === null){
if ($e_env === null) {
$e_env = $gameStor->getAll(false);
}
$eventID = $rawEvent['id'];
@@ -423,7 +428,7 @@ class TurnExecutionHelper
$event->tryRunEvent($e_env);
}
if($e_env !== null){
if ($e_env !== null) {
$gameStor->resetCache(true);
}
@@ -440,13 +445,16 @@ class TurnExecutionHelper
// 현재시간의 월턴시간 이후 분단위 장수 처리
[$executionOver, $currentTurn] = static::executeGeneralCommandUntil(
$date, $limitActionTime, $gameStor->year, $gameStor->month
$date,
$limitActionTime,
$gameStor->year,
$gameStor->month
);
if($currentTurn !== null){
if ($currentTurn !== null) {
$gameStor->turntime = $currentTurn;
}
//토너먼트 처리
processTournament();
//거래 처리
@@ -455,4 +463,4 @@ class TurnExecutionHelper
$gameStor->resetCache(true);
unlock();
}
}
}
+89
View File
@@ -0,0 +1,89 @@
<?php
namespace sammo;
class UserLogger
{
protected $userID;
protected $year;
protected $month;
protected $autoFlush;
protected $log = [];
function __construct(int $userID, ?int $year = null, ?int $month = null, bool $autoFlush = true)
{
$this->userID = $userID;
if ($year === null || $month === null) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['year', 'month']);
if ($year === null) {
$year = $gameStor->year;
}
if ($month === null) {
$month = $gameStor->month;
}
}
$this->year = $year;
$this->month = $month;
$this->autoFlush = $autoFlush;
}
public function __destruct()
{
if ($this->autoFlush) {
$this->flush();
}
}
public function rollback()
{
$backup = $this->log;
$this->log = [];
return $backup;
}
public function flush()
{
if(!$this->log){
return;
}
if(!$this->userID){
return;
}
$db = DB::db();
$date = TimeUtil::now();
$serverID = UniqueConst::$serverID;
$request = array_map(function ($textAndType) use ($date, $serverID) {
[$text, $type] = $textAndType;
return [
'user_id' => $this->userID,
'server_id' => $serverID,
'log_type' => $type,
'year' => $this->year,
'month' => $this->month,
'date' => $date,
'text' => $text
];
}, array_values($this->log));
$db->insert('user_record', $request);
$this->log = [];
}
public function push($text, string $type)
{
if (!$text) {
return;
}
if (is_array($text)) {
foreach ($text as $textItem) {
$this->log[] = [$textItem, $type];
}
return;
}
$this->log[] = [$text, $type];
}
}
+118 -88
View File
@@ -1,10 +1,13 @@
<?php
namespace sammo;
class WarUnitGeneral extends WarUnit{
class WarUnitGeneral extends WarUnit
{
protected $raw;
function __construct(General $general, array $rawNation, bool $isAttacker){
function __construct(General $general, array $rawNation, bool $isAttacker)
{
$this->general = $general;
$this->raw = $general->getRaw();
$this->rawNation = $rawNation; //read-only
@@ -15,43 +18,43 @@ class WarUnitGeneral extends WarUnit{
$cityLevel = $this->getCityVar('level');
if($isAttacker){
if ($isAttacker) {
//공격자 보정
if($cityLevel == 2){
if ($cityLevel == 2) {
$this->atmosBonus += 5;
}
if($rawNation['capital'] == $this->getCityVar('city')){
if ($rawNation['capital'] == $this->getCityVar('city')) {
$this->atmosBonus += 5;
}
}
else{
} else {
//수비자 보정
if($cityLevel == 1){
if ($cityLevel == 1) {
$this->trainBonus += 5;
}
else if($cityLevel == 3){
} else if ($cityLevel == 3) {
$this->trainBonus += 5;
}
}
}
function getName():string{
function getName(): string
{
return $this->general->getName();
}
function getCityVar(string $key){
function getCityVar(string $key)
{
return $this->general->getRawCity()[$key];
}
function setOppose(?WarUnit $oppose){
function setOppose(?WarUnit $oppose)
{
parent::setOppose($oppose);
$general = $this->general;
$this->general->increaseRankVar('warnum', 1);
if($this->isAttacker){
if ($this->isAttacker) {
$semiTurn = $general->getTurnTime();
}
else if($oppose !== null){
} else if ($oppose !== null) {
$semiTurn = $oppose->getGeneral()->getTurnTime();
}
$phase = $this->getRealPhase();
@@ -60,75 +63,94 @@ class WarUnitGeneral extends WarUnit{
$general->setVar('recent_war', $semiTurn);
}
function getMaxPhase():int{
function getMaxPhase(): int
{
$phase = $this->getCrewType()->speed;
$phase = $this->general->onCalcStat($this->general, 'initWarPhase', $phase, ['isAttacker'=>$this->isAttacker]);
$phase = $this->general->onCalcStat($this->general, 'initWarPhase', $phase, ['isAttacker' => $this->isAttacker]);
//maxPhase는 상대가 결정되기 전에 계산되므로 oppose를 호출할 수 없음
return $phase + $this->bonusPhase;
}
function addTrain(int $train){
function addTrain(int $train)
{
$this->general->increaseVarWithLimit('train', $train, 0, GameConst::$maxTrainByWar);
}
function addAtmos(int $atmos){
function addAtmos(int $atmos)
{
$this->general->increaseVarWithLimit('atmos', $atmos, 0, GameConst::$maxAtmosByWar);
}
function getDex(GameUnitDetail $crewType){
$rawDex = $this->general->getDex($crewType);
return $this->general->onCalcStat($this->general, 'dex'.$crewType->armType, $rawDex, [
'isAttacker'=>$this->isAttacker,
'opposeType'=>$this->oppose->getCrewType()
function getDex(GameUnitDetail $crewType)
{
$dex = $this->general->getDex($crewType);
$dex = $this->general->onCalcStat($this->general, 'dex' . $crewType->armType, $dex, [
'isAttacker' => $this->isAttacker,
'opposeType' => $this->oppose->getCrewType()
]);
$dex = $this->oppose->general->onCalcOpposeStat($this->general, 'dex' . $crewType->armType, $dex, [
'isAttacker' => $this->isAttacker,
'opposeType' => $this->oppose->getCrewType()
]);
return $dex;
}
function getComputedTrain(){
function getComputedTrain()
{
$train = $this->general->getVar('train');
$train = $this->general->onCalcStat($this->general, 'bonusTrain', $train, ['isAttacker'=>$this->isAttacker]);
$train = $this->general->onCalcStat($this->general, 'bonusTrain', $train, ['isAttacker' => $this->isAttacker]);
$train = $this->oppose->general->onCalcOpposeStat($this->general, 'bonusTrain', $train, ['isAttacker' => $this->isAttacker]);
$train += $this->trainBonus;
return $train;
}
function getComputedAtmos(){
function getComputedAtmos()
{
$atmos = $this->general->getVar('atmos');
$atmos = $this->general->onCalcStat($this->general, 'bonusAtmos', $atmos, ['isAttacker'=>$this->isAttacker]);
$atmos = $this->general->onCalcStat($this->general, 'bonusAtmos', $atmos, ['isAttacker' => $this->isAttacker]);
$atmos = $this->oppose->general->onCalcOpposeStat($this->general, 'bonusAtmos', $atmos, ['isAttacker' => $this->isAttacker]);
$atmos += $this->atmosBonus;
return $atmos;
}
function getComputedCriticalRatio():float{
function getComputedCriticalRatio(): float
{
$general = $this->general;
$criticalRatio = $this->getCrewType()->getCriticalRatio($general);
/** @var float $criticalRatio */
$criticalRatio = $general->onCalcStat($general, 'warCriticalRatio', $criticalRatio, ['isAttacker'=>$this->isAttacker]);
$criticalRatio = $general->onCalcStat($general, 'warCriticalRatio', $criticalRatio, ['isAttacker' => $this->isAttacker]);
$criticalRatio = $this->oppose->general->onCalcOpposeStat($general, 'warCriticalRatio', $criticalRatio, ['isAttacker' => $this->isAttacker]);
return $criticalRatio;
}
function getComputedAvoidRatio():float{
function getComputedAvoidRatio(): float
{
$general = $this->general;
$avoidRatio = $this->getCrewType()->avoid / 100;
$avoidRatio *= $this->getComputedTrain() / 100;
/** @var float $avoidRatio */
$avoidRatio = $general->onCalcStat($general, 'warAvoidRatio', $avoidRatio, ['isAttacker'=>$this->isAttacker]);
$avoidRatio = $general->onCalcStat($general, 'warAvoidRatio', $avoidRatio, ['isAttacker' => $this->isAttacker]);
$avoidRatio = $this->oppose->general->onCalcOpposeStat($general, 'warAvoidRatio', $avoidRatio, ['isAttacker' => $this->isAttacker]);
if($this->getOppose()->getCrewType()->armType == GameUnitConst::T_FOOTMAN){
if ($this->getOppose()->getCrewType()->armType == GameUnitConst::T_FOOTMAN) {
$avoidRatio *= 0.75;
}
return $avoidRatio;
}
function addWin(){
function addWin()
{
$general = $this->general;
$general->increaseRankVar('killnum', 1);
$oppose = $this->getOppose();
if($oppose instanceof WarUnitCity){
if ($oppose instanceof WarUnitCity) {
$general->increaseRankVar('occupied', 1);
}
@@ -137,74 +159,74 @@ class WarUnitGeneral extends WarUnit{
$this->addStatExp(1);
}
function addStatExp(int $value = 1){
function addStatExp(int $value = 1)
{
$general = $this->general;
if($this->crewType->armType == GameUnitConst::T_WIZARD) { // 귀병
if ($this->crewType->armType == GameUnitConst::T_WIZARD) { // 귀병
$general->increaseVar('intel_exp', $value);
} elseif($this->crewType->armType == GameUnitConst::T_SIEGE) { // 차병
} elseif ($this->crewType->armType == GameUnitConst::T_SIEGE) { // 차병
$general->increaseVar('leadership_exp', $value);
} else {
$general->increaseVar('strength_exp', $value);
}
}
function addLevelExp(float $value){
function addLevelExp(float $value)
{
$general = $this->general;
if(!$this->isAttacker){
if (!$this->isAttacker) {
$value *= 0.8;
}
$general->addExperience($value);
}
function addDedication(float $value){
function addDedication(float $value)
{
$general = $this->general;
$general->addDedication($value);
}
function addLose(){
function addLose()
{
$general = $this->general;
$general->increaseRankVar('deathnum', 1);
$this->addStatExp(1);
}
function computeWarPower(){
[$warPower,$opposeWarPowerMultiply] = parent::computeWarPower();
function computeWarPower()
{
[$warPower, $opposeWarPowerMultiply] = parent::computeWarPower();
$general = $this->general;
$cityID = $general->getCityID();
$officerLevel = $general->getVar('officer_level');
$officerCity = $general->getVar('officer_city');
if($this->isAttacker){
if($officerLevel == 12){
if ($this->isAttacker) {
if ($officerLevel == 12) {
$warPower *= 1.10;
}
else if($officerLevel == 11 | $officerLevel == 10 || $officerLevel == 8 || $officerLevel == 6){
} else if ($officerLevel == 11 | $officerLevel == 10 || $officerLevel == 8 || $officerLevel == 6) {
$warPower *= 1.05;
}
}
else{
if($officerLevel == 12){
} else {
if ($officerLevel == 12) {
$opposeWarPowerMultiply *= 0.90;
}
else if($officerLevel == 11 || $officerLevel == 9 || $officerLevel == 7 || $officerLevel == 5){
} else if ($officerLevel == 11 || $officerLevel == 9 || $officerLevel == 7 || $officerLevel == 5) {
$opposeWarPowerMultiply *= 0.95;
}
else if(2 <= $officerLevel && $officerLevel <= 4 && $officerCity == $cityID){
} else if (2 <= $officerLevel && $officerLevel <= 4 && $officerCity == $cityID) {
$opposeWarPowerMultiply *= 0.95;
}
}
$expLevel = $general->getVar('explevel');
if($this->getOppose() instanceof WarUnitCity){
if ($this->getOppose() instanceof WarUnitCity) {
$warPower *= 1 + $expLevel / 600;
}
else{
} else {
$warPower /= max(0.01, 1 - $expLevel / 300);
$opposeWarPowerMultiply *= max(0.01, 1 - $expLevel / 300);
}
[$specialMyWarPowerMultiply, $specialOpposeWarPowerMultiply] = $this->general->getWarPowerMultiplier($this);
$warPower *= $specialMyWarPowerMultiply;
@@ -212,18 +234,21 @@ class WarUnitGeneral extends WarUnit{
$this->warPower = $warPower;
$this->oppose->setWarPowerMultiply($opposeWarPowerMultiply);
return [$warPower,$opposeWarPowerMultiply];
return [$warPower, $opposeWarPowerMultiply];
}
function getHP():int{
function getHP(): int
{
return $this->general->getVar('crew');
}
function addDex(GameUnitDetail $crewType, float $exp){
function addDex(GameUnitDetail $crewType, float $exp)
{
$this->general->addDex($crewType, $exp, false);
}
function decreaseHP(int $damage):int{
function decreaseHP(int $damage): int
{
$general = $this->general;
$damage = min($damage, $general->getVar('crew'));
@@ -232,7 +257,7 @@ class WarUnitGeneral extends WarUnit{
$general->increaseVar('crew', -$damage);
$addDex = $damage;
if(!$this->isAttacker){
if (!$this->isAttacker) {
$addDex *= 0.9;
}
$this->addDex($this->oppose->getCrewType(), $addDex);
@@ -240,12 +265,13 @@ class WarUnitGeneral extends WarUnit{
return $general->getVar('crew');
}
function increaseKilled(int $damage):int{
function increaseKilled(int $damage): int
{
$general = $this->general;
$this->addLevelExp($damage / 50);
$rice = $damage / 100;
if(!$this->isAttacker){
if (!$this->isAttacker) {
$rice *= 0.8;
}
@@ -253,9 +279,9 @@ class WarUnitGeneral extends WarUnit{
$rice *= getTechCost($this->getNationVar('tech'));
$general->increaseVarWithLimit('rice', -$rice, 0);
$addDex = $damage;
if(!$this->isAttacker){
if (!$this->isAttacker) {
$addDex *= 0.9;
}
$this->addDex($this->getCrewType(), $addDex);
@@ -265,15 +291,16 @@ class WarUnitGeneral extends WarUnit{
return $this->killed;
}
function tryWound():bool{
function tryWound(): bool
{
$general = $this->general;
if($this->hasActivatedSkillOnLog('부상무효')){
if ($this->hasActivatedSkillOnLog('부상무효')) {
return false;
}
if($this->hasActivatedSkillOnLog('퇴각부상무효')){
if ($this->hasActivatedSkillOnLog('퇴각부상무효')) {
return false;
}
if(!Util::randBool(0.05)){
if (!Util::randBool(0.05)) {
return false;
}
@@ -285,25 +312,28 @@ class WarUnitGeneral extends WarUnit{
return true;
}
function continueWar(&$noRice):bool{
function continueWar(&$noRice): bool
{
$general = $this->general;
if($this->getHP() <= 0){
if ($this->getHP() <= 0) {
$noRice = false;
return false;
}
if($general->getVar('rice') <= $this->getHP() / 100){
if ($general->getVar('rice') <= $this->getHP() / 100) {
$noRice = true;
return false;
}
return true;
}
function checkStatChange():bool{
function checkStatChange(): bool
{
return $this->general->checkStatChange();
}
function finishBattle(){
if($this->isFinished){
function finishBattle()
{
if ($this->isFinished) {
return;
}
$this->clearActivatedSkill();
@@ -313,11 +343,11 @@ class WarUnitGeneral extends WarUnit{
$general->increaseRankVar('killcrew', $this->killed);
$general->increaseRankVar('deathcrew', $this->dead);
if($this->getOppose() instanceof WarUnitGeneral){
if ($this->getOppose() instanceof WarUnitGeneral) {
$general->increaseRankVar('killcrew_person', $this->killed);
$general->increaseRankVar('deathcrew_person', $this->dead);
}
$general->updateVar('rice', Util::round($general->getVar('rice')));
$general->updateVar('experience', Util::round($general->getVar('experience')));
$general->updateVar('dedication', Util::round($general->getVar('dedication')));
@@ -325,10 +355,10 @@ class WarUnitGeneral extends WarUnit{
$this->checkStatChange();
}
function applyDB(\MeekroDB $db):bool{
function applyDB(\MeekroDB $db): bool
{
$affected = $this->getGeneral()->applyDB($db);
$this->getLogger()->flush();
return $affected;
}
}
}
@@ -25,10 +25,12 @@ class che_계략발동 extends BaseWarUnitTrigger{
$general = $self->getGeneral();
[$magic, $damage] = $selfEnv['magic'];
$damage = $general->onCalcStat($general, 'warMagicFailDamage', $damage, $magic);
$damage = $oppose->getGeneral()->onCalcOpposeStat($general, 'warMagicFailDamage', $damage, $magic);
$josaUl = \sammo\JosaUtil::pick($magic, '을');
$general->getLogger()->pushGeneralBattleDetailLog("<D>{$magic}</>{$josaUl} <C>성공</>했다!", ActionLogger::PLAIN);
$oppose->getLogger()->pushGeneralBattleDetailLog("<D>{$magic}</>에 당했다!", ActionLogger::PLAIN);
@@ -33,11 +33,13 @@ class che_계략시도 extends BaseWarUnitTrigger{
if($self->hasActivatedSkill('계략불가')){
return true;
}
$magicTrialProb = $general->getIntel(true, true, true, false) / 100;
$magicTrialProb *= $crewType->magicCoef;
$magicTrialProb = $general->onCalcStat($general, 'warMagicTrialProb', $magicTrialProb);
$magicTrialProb = $oppose->getGeneral()->onCalcOpposeStat($general, 'warMagicTrialProb', $magicTrialProb);
if($magicTrialProb <= 0){
return true;
}
@@ -45,16 +47,14 @@ class che_계략시도 extends BaseWarUnitTrigger{
if($self->getPhase() == 0){
$magicTrialProb *= 3;
}
if(!Util::randBool($magicTrialProb)){
return true;
}
$magicSuccessProb = 0.7;
$magicSuccessProb = $general->onCalcStat($general, 'warMagicSuccessProb', $magicSuccessProb);
if($self->hasActivatedSkill('계략약화')){
$magicSuccessProb -= 0.1; //NOTE: 앞으로 이건 oppose의 onCalcStat에 들어가야하지 않을까?
}
$magicSuccessProb = $oppose->getGeneral()->onCalcOpposeStat($general, 'warMagicSuccessProb', $magicSuccessProb);
if($oppose instanceof WarUnitCity){
$magic = Util::choiceRandom(array_keys(static::$tableToCity));
@@ -66,6 +66,8 @@ class che_계략시도 extends BaseWarUnitTrigger{
}
$successDamage = $general->onCalcStat($general, 'warMagicSuccessDamage', $successDamage, $magic);
$successDamage = $oppose->getGeneral()->onCalcOpposeStat($general, 'warMagicSuccessDamage', $successDamage, $magic);
$self->activateSkill('계략시도', $magic);
if(Util::randBool($magicSuccessProb)){
@@ -76,7 +78,7 @@ class che_계략시도 extends BaseWarUnitTrigger{
$self->activateSkill('계략실패');
$selfEnv['magic'] = [$magic, $failDamage];
}
return true;
}
}
@@ -27,11 +27,12 @@ class che_계략실패 extends BaseWarUnitTrigger{
[$magic, $damage] = $selfEnv['magic'];
$damage = $general->onCalcStat($general, 'warMagicFailDamage', $damage, $magic);
$damage = $oppose->getGeneral()->onCalcOpposeStat($general, 'warMagicFailDamage', $damage, $magic);
$josaUl = \sammo\JosaUtil::pick($magic, '을');
$general->getLogger()->pushGeneralBattleDetailLog("<D>{$magic}</>{$josaUl} <R>실패</>했다!", ActionLogger::PLAIN);
$oppose->getLogger()->pushGeneralBattleDetailLog("<D>{$magic}</>{$josaUl} 간파했다!", ActionLogger::PLAIN);
$self->multiplyWarPowerMultiply(1/$damage);
$oppose->multiplyWarPowerMultiply($damage);
@@ -14,6 +14,7 @@ class che_반계시도 extends BaseWarUnitTrigger{
public function __construct(WarUnit $unit, int $raiseType = 0, float $prob = 0.4){
$this->object = $unit;
$this->raiseType = $raiseType;
$this->prob = $prob;
}
+1
View File
@@ -10,6 +10,7 @@ interface iAction{
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float;
public function onCalcStat(General $general, string $statName, $value, $aux=null);
public function onCalcOpposeStat(General $general, string $statName, $value, $aux=null);
public function onCalcStrategic(string $turnType, string $varType, $value);
public function onCalcNationalIncome(string $type, $amount);
+1 -1
View File
@@ -2,7 +2,7 @@
"title": "【가상모드19b】 진유저무쌍! (대형 지도)",
"startYear": 180,
"history": [
"<C>●</>180년 1월:<L><b>【가상모드19】</b>진유저무쌍! (대형 지도)</>",
"<C>●</>180년 1월:<L><b>【가상모드19】</b>진유저무쌍! (대형 지도)</>",
"<C>●</>180년 1월:<L><b>【이벤트】</b></>고대장수 다 덤벼라! 유저가 최강이다!"
],
"stat": {
+113
View File
@@ -0,0 +1,113 @@
{
"title": "【가상모드23】 CookieRun : Kingdom",
"startYear": 180,
"history": [
"<C>●</>180년 1월:<L><b>【가상모드23】</b>CookieRun : Kingdom</>",
"<C>●</>180년 1월:<L><b>【이벤트】</b></>쿠키들과 함께하는 삼모전"
],
"stat": {
"total": 200,
"min": 10,
"max": 90,
"npcTotal":180,
"npcMax":70,
"npcMin":10,
"chiefMin": 60
},
"iconPath": "쿠키런킹덤",
"fiction": 1,
"nation":[
],
"map":{
"mapName":"miniche",
"unitSet":"che"
},
"diplomacy":[],
"general":[
[30, "커스터드3세", null, 0, null, 60, 60, 60, 0, 160, 300, null, null, "새로운 백성이로구나. 반가워!"],
[30, "클로버", null, 0, null, 71, 49, 71, 0, 160, 300, null, null, "여러분의 모험에 행운이 깃들길..."],
[50, "마들렌", null, 0, null, 73, 57, 73, 0, 160, 300, null, null, "빛의 신께 세상을 구하라는 명을 받은 쿠키가 바로 나다!"],
[50, "호밀", null, 0, null, 73, 65, 65, 0, 160, 300, null, null, "애송이들! 그렇게 부드러워서야 되겠어?"],
[50, "에스프레소", null, 0, null, 75, 55, 75, 0, 160, 300, null, null, "커피마법이라고 다를 것 없습니다?"],
[50, "라떼", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "쓰디 쓴 실패라도 부드러운 우유 몇 방울이면 달콤해질거야"],
[50, "아몬드", null, 0, null, 69, 30, 100, 0, 160, 300, null, null, "당신을 마법 행정 규약 위반으로 체포합니다"],
[50, "블랙레이즌", null, 0, null, 65, 70, 60, 0, 160, 300, null, null, "깜깜한 어둠 속도 상관 없어. 난 전부 보이니까!"],
[60, "감초", null, 0, null, 70, 10, 120, 0, 160, 300, null, null, "나도 할 땐 하는 쿠키야!"],
[60, "독버섯", null, 0, null, 70, 60, 70, 0, 160, 300, null, null, "버서엇...?"],
[60, "딸기크레페", null, 0, null, 70, 60, 70, 0, 160, 300, null, null],
[70, "퓨어바닐라", null, 0, null, 90, 45, 90, 0, 160, 300, null, null, "힘들 땐 힘들다고 말해도 괜찮아요."],
[60, "다크초코", null, 0, null, 70, 60, 70, 0, 160, 300, null, null, "그저… 영웅이 되고 싶었을 뿐…"],
[60, "석류", null, 0, null, 75, 55, 75, 0, 160, 300, null, null, "영원히 그분만을 섬기리…"],
[999, "설탕노움", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[10, "The브레이브", null, 0, null, 69, 51, 69, 0, 160, 300, null, null, "모험은 이제부터 시작이야!"],
[10, "스트로베리", null, 0, null, 70, 50, 70, 0, 160, 300, null, null, "쿠키생은 혼자야…"],
[10, "매지션", null, 0, null, 66, 54, 66, 0, 160, 300, null, null, "가슴은 뜨겁게 머리는 앗 차거!"],
[10, "에인절", null, 0, null, 63, 57, 63, 0, 160, 300, null, null, "새처럼 날아가 볼까요…"],
[10, "비트", null, 0, null, 64, 56, 64, 0, 160, 300, null, null, "벌써 이곳에서 1000일을 버텼지!"],
[10, "The머슬", null, 0, null, 70, 50, 70, 0, 160, 300, null, null, "이번엔 스쿼트다! 하나! 둘!"],
[10, "닌자", null, 0, null, 63, 57, 63, 0, 160, 300, null, null, "허공을 가르고 바람을 밟는다!"],
[30, "용사", null, 0, null, 67, 58, 67, 0, 160, 300, null, null, "더 강해져야 해!"],
[30, "알케미스트", null, 0, null, 61, 64, 61, 0, 160, 300, null, null, "내가 어떤 걸 만들어 내는지 잘 보라구~!"],
[30, "체리", null, 0, null, 66, 59, 66, 0, 160, 300, null, null, "어랏? 터져버렸네~? 미안...일부러 그랬어~ 헤헷!"],
[30, "버블껌", null, 0, null, 65, 60, 65, 0, 160, 300, null, null, "껌은 씹는 것 보다 쏘는 게 더 재밌어!"],
[30, "블랙베리", null, 0, null, 65, 60, 65, 0, 160, 300, null, null, "맡기실 일이 있다면 뭐든 말씀하세요."],
[30, "팬케이크", null, 0, null, 52, 73, 52, 0, 160, 300, null, null, "나 도토리젤리 안 줄 거야?"],
[30, "The프린세스", null, 0, null, 60, 65, 60, 0, 160, 300, null, null, "나들이하기 좋은 날이네~!"],
[30, "아보카도", null, 0, null, 67, 58, 67, 0, 160, 300, null, null, "가장 맛있는 싸움은? 보쌈! 와하하!"],
[30, "어니언", null, 0, null, 72, 53, 72, 0, 160, 300, null, null, "으아아아아앙~"],
[30, "익스플로러", null, 0, null, 65, 60, 65, 0, 160, 300, null, null, "가보고 싶은 곳이 너무 많아!"],
[30, "캐롯", null, 0, null, 71, 54, 71, 0, 160, 300, null, null, "밭일하러 나갈 시간이야!"],
[60, "뱀파이어", null, 0, null, 58, 72, 58, 0, 160, 300, null, null, "나랑 포도주스 한 잔 어때?"],
[50, "스파클링", null, 0, null, 70, 60, 70, 0, 160, 300, null, null, "승리를 위한 한 잔이 필요하겠군요!"],
[50, "칠리", null, 0, null, 65, 65, 65, 0, 160, 300, null, null, "어이! 주머니 조심하라구!"],
[50, "자색고구마", null, 0, null, 65, 65, 65, 0, 160, 300, null, null, "나랑 싸울 쿠키 다 나와!"],
[50, "눈설탕", null, 0, null, 79, 51, 79, 0, 160, 300, null, null, "안녕? 반가워~ 나랑... 눈싸움할래?"],
[50, "정글전사", null, 0, null, 80, 50, 80, 0, 160, 300, null, null, "친구…들을… 지켜야… 해…"],
[50, "민트초코", null, 0, null, 76, 54, 76, 0, 160, 300, null, null, "어떤 음악을 들려드릴까요?"],
[50, "허브", null, 0, null, 71, 59, 71, 0, 160, 300, null, null, "무럭무럭 자라렴~"],
[50, "우유", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "평화를 위해 어둠과 맞서 싸우리라!"],
[50, "웨어울프", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "다가오지 마… 다쳐…"],
[50, "구미호", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "나한테 반하면 어떻게 되는지 궁금해?"],
[50, "슈크림", null, 0, null, 71, 59, 71, 0, 160, 300, null, null, "저도 이제 어엿한 마법사라구요!"],
[150, "케이크들개", null, 0, null, 40, 80, 40, 0, 160, 300, null, null],
[999, "곰젤리", null, 0, null, 40, 80, 40, 0, 160, 300, null, null],
[999, "곰젤리역장", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "후르츠칸앵무", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "순례자", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "은행강도", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "무녀", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[150, "역사선생님", null, 0, null, 85, 45, 85, 0, 160, 300, null, null, "오늘 확실히 가르쳐 주겠습니다! 도서관의 규칙을!"],
[150, "화학선생님", null, 0, null, 85, 45, 85, 0, 160, 300, null, null, "화학실에 멋대로 침입한 벌을 내리겠다!!"],
[150, "전술선생님", null, 0, null, 85, 45, 85, 0, 160, 300, null, null, "으하하하!! 그럼 어디 한 번 시험해 볼까! 너의 전술을!"],
[150, "꿈꾸는 바할로모트", null, 0, null, 90, 40, 90, 0, 160, 300, null, "환술", "난 이 학교의 교장이니까 말일세!"],
[999, "치료사", null, 0, null, 65, 55, 65, 0, 160, 300, null, null],
[999, "커스터드총리", null, 0, null, 63, 63, 63, 0, 160, 300, null, null],
[150, "3단케이크마녀", null, 0, null, 70, 70, 70, 0, 160, 300, null, null]
],
"general_ex":[
[999, "바람궁수", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "달빛술사", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "바다요정", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "불꽃정령", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[150, "어둠마녀", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "천년나무", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "다크카카오", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "세인트릴리", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "홀리베리", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "골드치즈", null, 0, null, 60, 60, 60, 0, 160, 300, null, null]
],
"events":[
[
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
["CreateManyNPC", 30],
["DeleteEvent"]
],
[
["Date", "==", 181, 1],
["RaiseNPCNation"],
["DeleteEvent"]
]
]
}
+20 -5
View File
@@ -10,6 +10,7 @@ html {
color: white;
}
//TODO: 삭제!!
table.tb_layout {
border-collapse: collapse;
padding: 0px;
@@ -17,7 +18,8 @@ table.tb_layout {
word-break: break-all;
}
html, body{
html,
body {
font-size: 13px;
}
@@ -30,10 +32,23 @@ html, body{
}
.float-left{
float:left;
.float-left {
float: left;
}
.float-right{
float:right;
.float-right {
float: right;
}
.a-right {
text-align: right;
}
.a-left {
text-align: left;
}
.a-center {
text-align: center;
}
-23
View File
@@ -1,23 +0,0 @@
#inheritance_list{
display: flex;
flex-wrap: wrap;
}
.inherit_padding{
width: 33%;
padding: 10px 2px;
}
.inherit_item{
width: 33%;
padding: 10px 2px;
}
.col-form-label{
text-align:right;
padding-right:2ch;
}
.inherit_value{
text-align: right;
}
+21 -1
View File
@@ -438,7 +438,7 @@ CREATE TABLE `tournament` (
`prmt` INT(1) NULL DEFAULT 0,
PRIMARY KEY (`seq`),
INDEX `grp` (`grp`, `grp_no`)
)
)
COLLATE='utf8mb4_general_ci'
ENGINE=Aria;
@@ -651,4 +651,24 @@ CREATE TABLE `rank_data` (
)
COLLATE='utf8mb4_general_ci'
ENGINE=Aria
;
CREATE TABLE IF NOT EXISTS `user_record` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`user_id` INT(11) NOT NULL,
`server_id` CHAR(20) NOT NULL,
`log_type` VARCHAR(20) NOT NULL,
`year` INT(4) NOT NULL,
`month` INT(2) NOT NULL,
`date` DATETIME NULL DEFAULT NULL,
`text` TEXT NOT NULL,
PRIMARY KEY (`id`),
INDEX `date1` (`user_id`, `server_id`, `log_type`, `year`, `month`, `id`),
INDEX `date2` (`user_id`, `server_id`, `log_type`, `date`, `id`),
INDEX `date3` (`server_id`, `date`),
INDEX `date4` (`server_id`, `year`, `month`, `date`),
INDEX `plain` (`user_id`, `log_type`, `id`)
)
DEFAULT CHARSET=utf8mb4
ENGINE=Aria
;
-1
View File
@@ -61,7 +61,6 @@
<script lang="ts">
import "../scss/bootstrap5.scss";
import "../scss/inheritPoint.scss";
import "../scss/game_bg.scss";
import "../../css/config.css";
+606
View File
@@ -0,0 +1,606 @@
<template>
<top-back-bar title="장수 생성" />
<div id="container" class="bg0">
<div class="row bg1">
<div class="col col-md-11 col-9 center align-self-center">
임관 권유 메시지
</div>
<div class="col col-md-1 col-3">
<label
><input type="checkbox" v-model="displayTable" />{{
displayTable ? "숨기기" : "보이기"
}}</label
>
</div>
</div>
<CTable responsive v-if="displayTable">
<CTableBody>
<CTableRow
class="nation-row"
v-for="nation in nationList"
:key="nation.nation"
>
<CTableHeaderCell
scope="row"
class="a-center p-0"
:style="{
backgroundColor: nation.color,
color: isBrightColor(nation.color) ? 'black' : 'white',
}"
><div class="nation-name">
{{ nation.name }}
</div>
</CTableHeaderCell>
<CTableDataCell class="p-0">
<div
class="nation-info"
v-html="nation.scoutmsg ?? '-'"
></div></CTableDataCell></CTableRow
></CTableBody>
</CTable>
<!-- 국가 설명 -->
<div class="row bg1"><div class="col center">장수 생성</div></div>
<div class="forms">
<div class="row">
<div class="col col-md-4 col-3 a-right align-self-center">장수명</div>
<div class="col col-md-3 col-9 align-self-center">
<input v-model="args.name" class="form-control" />
</div>
<div class="col col-md-1 col-3 a-right align-self-center">
전콘 사용
</div>
<div class="col col-md-4 col-9 align-self-center">
<img style="height: 64px; width: 64px" :src="iconPath" /><label
><input type="checkbox" v-model="args.pic" /> 사용</label
>
</div>
<div class="col col-md-4 col-3 align-self-center a-right">성격</div>
<div class="col col-md-8 col-9 align-self-center">
<div class="row">
<div class="col col-md-3 col-4 align-self-center">
<select
class="form-select form-inline"
style="max-width: 20ch"
v-model="args.character"
>
<option
v-for="(personalityObj, key) in availablePersonality"
:key="key"
:value="key"
>
{{ personalityObj.name }}
</option>
</select>
</div>
<div class="col col-md-9 col-8 align-self-center">
<small class="text-muted">{{
availablePersonality[args.character].info
}}</small>
</div>
</div>
</div>
</div>
<!--<div class="row">
<div class="col">
계정관리에서 자신만을 표현할 있는 아이콘을 업로드 해보세요!
</div>
</div>-->
<div class="row" style="margin-top: 1em">
<div class="col col-md-4 col-3 a-right align-self-center">
능력치<br /><small class="text-muted">//</small>
</div>
<div class="col col-md-2 col-3 align-self-center">
<input type="number" class="form-control" v-model="args.leadership" />
</div>
<div class="col col-md-2 col-3 align-self-center">
<input type="number" class="form-control" v-model="args.strength" />
</div>
<div class="col col-md-2 col-3 align-self-center">
<input type="number" class="form-control" v-model="args.intel" />
</div>
</div>
<div class="row" style="margin-top: 1em">
<div class="col col-md-4 col-3 a-right align-self-center">
능력치 조절
</div>
<div class="col col-md-8 col-9">
<b-button variant="secondary" class="stat-btn" @click="randStatRandom"
>랜덤형</b-button
>
<b-button
variant="secondary"
class="stat-btn"
@click="randStatLeadPow"
>통솔무력형</b-button
>
<b-button
variant="secondary"
class="stat-btn"
@click="randStatLeadInt"
>통솔지력형</b-button
>
<b-button variant="secondary" class="stat-btn" @click="randStatPowInt"
>무력지력형</b-button
>
</div>
</div>
</div>
<div class="row" style="border-top: solid 1px #aaa; margin-top: 0.5em">
<div class="col a-center" style="color: orange">
모든 능력치는 ( {{ stats.min }} &lt;= 능력치 &lt;= {{ stats.max }} )
사이로 잡으셔야 합니다.<br />
외의 능력치는 가입되지 않습니다.
</div>
</div>
<div class="row">
<div class="col a-center">
능력치의 총합은 {{ stats.total }} 입니다. 가입후 {{ stats.bonusMin }} ~
{{ stats.bonusMax }} 능력치 보너스를 받게 됩니다.<br />
임의의 도시에서 재야로 시작하며 건국과 임관은 게임 내에서 실행합니다.
</div>
</div>
<div class="row bg1">
<div class="col col-md-11 col-9 center align-self-center">
유산 포인트 사용
</div>
<div class="col col-md-1 col-3">
<label
><input type="checkbox" v-model="displayInherit" />{{
displayInherit ? "숨기기" : "보이기"
}}</label
>
</div>
</div>
<div class="inherit-block" v-if="displayInherit">
<div class="row">
<div class="col">
<NumberInputWithInfo
title="보유한 유산 포인트"
v-model="inheritTotalPoint"
:readonly="true"
/>
</div>
<div class="col">
<NumberInputWithInfo
title="필요 유산 포인트"
v-model="inheritRequiredPoint"
:readonly="true"
/>
</div>
</div>
<hr />
<div class="row">
<div class="col col-md-6 col-sm-6 col-12 p-2 align-self-center">
<div class="row">
<div class="col col-6 a-right align-self-center">천재로 생성</div>
<div class="col col-6 align-self-center">
<select
class="form-select form-inline"
style="max-width: 20ch"
v-model="args.inheritSpecial"
>
<option :value="undefined">사용안함</option>
<option
v-for="(inheritSpecial, key) in availableInheritSpecial"
:key="key"
:value="key"
>
{{ inheritSpecial.name }}
</option>
</select>
</div>
</div>
<div class="col align-self-center">
<small
class="text-muted"
v-html="
(availableInheritSpecial[args.inheritSpecial] ?? { info: '' })
.info
"
/>
</div>
</div>
<div class="col col-md-6 col-sm-6 col-12 p-2 align-self-center">
<div class="row">
<div class="col col-6 a-right align-self-center">도시</div>
<div class="col col-6 align-self-center">
<select
class="form-select form-inline"
style="max-width: 20ch"
v-model="args.inheritCity"
>
<option :value="undefined">사용안함</option>
<option
v-for="city in availableInheritCity"
:key="city[0]"
:value="city[0]"
>
{{ `[${city[1]}] ${city[2]}` }}
</option>
</select>
</div>
</div>
</div>
<div class="col col-md-6 col-sm-6 col-12 p-2 align-self-center">
<div class="a-center">
<label
><input type="checkbox" v-model="inheritTurnTimeSet" /> 시간
고정</label
>
</div>
<div class="row turn_time_pad">
<div class="col col-md-4 offset-md-3 col-4 offset-3">
<NumberInputWithInfo
:readonly="!inheritTurnTimeSet"
:min="0"
:max="1 - turnterm"
v-model="inheritTurnTimeMinute"
:right="true"
title="분"
/>
</div>
<div class="col col-md-4 col-4">
<NumberInputWithInfo
:readonly="!inheritTurnTimeSet"
:min="0"
:max="60"
v-model="inheritTurnTimeSecond"
:right="true"
title="초"
/>
</div>
</div>
</div>
<div class="col col-md-6 col-12 p-2">
<div class="a-center">추가 능력치 고정</div>
<div class="row">
<div class="col">
<NumberInputWithInfo
title="통솔"
v-model="args.inheritBonusStat[0]"
/>
</div>
<div class="col">
<NumberInputWithInfo
title="무력"
v-model="args.inheritBonusStat[1]"
/>
</div>
<div class="col">
<NumberInputWithInfo
title="지력"
v-model="args.inheritBonusStat[2]"
/>
</div>
</div>
</div>
</div>
</div>
<div class="row" style="border-top: solid 1px #aaa">
<div class="col a-center" style="margin: 0.5em">
<b-button color="primary" @click="submitForm">장수 생성</b-button
>&nbsp;<b-button color="secondary" @click="resetArgs"
>다시 입력</b-button
>
</div>
</div>
</div>
</template>
<script lang="ts">
import "../scss/bootstrap5.scss";
import "../scss/game_bg.scss";
import { defineComponent } from "vue";
import TopBackBar from "./components/TopBackBar.vue";
import {
CTable,
CTableBody,
CTableRow,
CTableHeaderCell,
CTableDataCell,
} from "@coreui/vue/src/components/table";
import { getIconPath } from "./util/getIconPath";
import { isBrightColor } from "./util/isBrightColor";
import {
abilityLeadint,
abilityLeadpow,
abilityPowint,
abilityRand,
} from "./util/generalStats";
import { clone, shuffle, sum } from "lodash";
import axios from "axios";
import { InvalidResponse } from "./defs";
import NumberInputWithInfo from "./components/NumberInputWithInfo.vue";
declare const nationList: {
nation: number;
name: string;
color: string;
scout: number;
scoutmsg?: string;
}[];
declare const availablePersonality: {
[key: string]: {
name: string;
info: string;
};
};
declare const availableInheritSpecial: {
[key: string]: {
name: string;
info: string;
};
};
declare const availableInheritCity: [number, string, string][];
declare const turnterm: number;
declare const member: {
name: string;
grade: number;
picture: string;
imgsvr: 0 | 1;
};
declare const stats: {
min: number;
max: number;
total: number;
bonusMin: number;
bonusMax: number;
};
declare const inheritPoints: {
special: number;
turnTime: number;
city: number;
stat: number;
};
declare const serverID: string;
declare const inheritTotalPoint: number;
declare module "@vue/runtime-core" {
interface ComponentCustomProperties {
member: typeof member;
}
}
type APIArgs = {
name: string;
leadership: number;
strength: number;
intel: number;
pic: boolean;
character: string;
inheritSpecial?: string;
inheritTurntime?: number;
inheritCity?: number;
inheritBonusStat?: [number, number, number];
};
export default defineComponent({
name: "Join",
components: {
TopBackBar,
CTable,
CTableBody,
CTableRow,
CTableHeaderCell,
CTableDataCell,
NumberInputWithInfo,
},
data() {
const displayTable = JSON.parse(
localStorage.getItem(`conf.${serverID}.join.displayTable`) ?? "true"
);
const displayInherit = JSON.parse(
localStorage.getItem(`conf.${serverID}.join.displayInherit`) ?? "true"
);
const nationListShuffled = shuffle(nationList);
const args: APIArgs = {
name: member.name,
leadership: stats.total - 2 * Math.floor(stats.total / 3),
strength: Math.floor(stats.total / 3),
intel: Math.floor(stats.total / 3),
pic: true,
character: "Random",
inheritCity: undefined,
inheritBonusStat: [0, 0, 0],
inheritSpecial: undefined,
inheritTurntime: undefined,
};
availableInheritCity.sort((lhs, rhs) => {
const rC = lhs[1].localeCompare(rhs[1]);
if (rC != 0) return rC;
return lhs[2].localeCompare(rhs[2]);
});
return {
displayTable,
displayInherit,
availablePersonality,
availableInheritSpecial,
availableInheritCity,
member: member,
stats,
args,
nationList: nationListShuffled,
isBrightColor,
inheritTotalPoint,
inheritTurnTimeSet: false,
inheritTurnTimeMinute: 0,
inheritTurnTimeSecond: 0,
turnterm,
};
},
watch: {
displayTable(newValue: boolean) {
localStorage.setItem(
`conf.${serverID}.join.displayTable`,
JSON.stringify(newValue)
);
},
displayInherit(newValue: boolean) {
localStorage.setItem(
`conf.${serverID}.join.displayInherit`,
JSON.stringify(newValue)
);
},
inheritTurnTimeMinute(newValue: number) {
if (!this.inheritTurnTimeSet) {
this.args.inheritTurntime = undefined;
return;
}
this.args.inheritTurntime = newValue * 60 + this.inheritTurnTimeSecond;
},
inheritTurnTimeSecond(newValue: number) {
if (!this.inheritTurnTimeSet) {
this.args.inheritTurntime = undefined;
return;
}
this.args.inheritTurntime = this.inheritTurnTimeMinute * 60 + newValue;
},
inheritTurnTimeSet(newValue: boolean) {
if (!newValue) {
this.args.inheritTurntime = undefined;
return;
}
this.args.inheritTurntime =
this.inheritTurnTimeMinute * 60 + this.inheritTurnTimeSecond;
},
},
computed: {
iconPath() {
if (this.args.pic) {
return getIconPath(this.member.imgsvr, this.member.picture);
}
return getIconPath(0, "default.jpg");
},
inheritRequiredPoint() {
let inheritRequiredPoint = 0;
if (this.args.inheritCity !== undefined) {
inheritRequiredPoint += inheritPoints.city;
}
if (this.args.inheritSpecial !== undefined) {
inheritRequiredPoint += inheritPoints.special;
}
if (this.args.inheritTurntime !== undefined) {
inheritRequiredPoint += inheritPoints.turnTime;
}
if (
this.args.inheritBonusStat !== undefined &&
sum(this.args.inheritBonusStat) != 0
) {
inheritRequiredPoint += inheritPoints.stat;
}
return inheritRequiredPoint;
},
},
methods: {
randStatRandom() {
[this.args.leadership, this.args.strength, this.args.intel] =
abilityRand();
},
randStatLeadPow() {
[this.args.leadership, this.args.strength, this.args.intel] =
abilityLeadpow();
},
randStatLeadInt() {
[this.args.leadership, this.args.strength, this.args.intel] =
abilityLeadint();
},
randStatPowInt() {
[this.args.leadership, this.args.strength, this.args.intel] =
abilityPowint();
},
resetArgs() {
this.args.name = member.name;
this.args.pic = true;
this.args.character = "Random";
this.args.leadership = stats.total - 2 * Math.floor(stats.total / 3);
this.args.strength = Math.floor(stats.total / 3);
this.args.intel = Math.floor(stats.total / 3);
},
async submitForm() {
// ?
const args = clone(this.args);
let result: InvalidResponse;
try {
const response = await axios({
url: "api.php",
method: "post",
responseType: "json",
data: {
path: ["General", "Join"],
args,
},
});
result = response.data;
if (!result.result) {
throw result.reason;
}
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
alert(
"정상적으로 생성되었습니다. \n위키와 팁/강좌 게시판을 꼭 읽어보세요!"
);
location.href = "./";
},
},
});
</script>
<style>
#container {
width: 100%;
max-width: 1000px;
margin: auto;
border: solid 1px #888888;
overflow: hidden;
}
.forms {
padding: 0 6px;
}
.stat-btn {
width: 8em;
margin-right: 1px;
margin-bottom: 1px;
}
.nation-row {
max-height: 200px;
}
.nation-name {
width: 128px;
}
.nation-info {
max-height: 200px;
overflow-y: hidden;
width: 870px;
}
.col-form-label {
text-align: right;
}
.turn_time_pad .col-form-label{
text-align: left;
}
</style>
+5 -10
View File
@@ -50,7 +50,7 @@
<NumberInputWithInfo
v-model="nationPolicy.reqHumanWarUrgentRice"
:step="100"
title="유저전투장 긴급포상 "
title="유저전투장 긴급포상 "
>유저장긴급포상시 이보다 쌀이 적은 장수에게 포상합니다.<br />0이면
기본 병종으로 {{ (defaultStatMax * 100).toLocaleString() }} * 6 사살
가능한 쌀을 기준으로 하며, 수치는 현재
@@ -298,9 +298,8 @@
<i class="bi bi-list"></i>&nbsp;&nbsp;{{ element.id
}}<button
class="btn btn-sm float-right btn-secondary py-0 px-1"
v-c-tooltip="actionHelpText[element.id]"
v-b-tooltip.hover :title="actionHelpText[element.id]"
>
<!-- FIXME: v-c-tooltip 동작이 조금 묘하다. 버전 문제인가? -->
<i class="bi bi-question-lg"></i>
</button>
</div>
@@ -320,7 +319,7 @@
<i class="bi bi-list"></i>&nbsp;&nbsp;{{ element.id
}}<button
class="btn btn-sm float-right btn-secondary py-0 px-1"
v-c-tooltip="actionHelpText[element.id]"
v-b-tooltip.hover :title="actionHelpText[element.id]"
>
<i class="bi bi-question-lg"></i>
</button>
@@ -391,7 +390,7 @@
<i class="bi bi-list"></i>&nbsp;&nbsp;{{ element.id
}}<button
class="btn btn-sm float-right btn-secondary py-0 px-1"
v-c-tooltip="actionHelpText[element.id]"
v-b-tooltip.hover :title="actionHelpText[element.id]"
>
<i class="bi bi-question-lg"></i>
</button>
@@ -412,7 +411,7 @@
<i class="bi bi-list"></i>&nbsp;&nbsp;{{ element.id
}}<button
class="btn btn-sm float-right btn-secondary py-0 px-1"
v-c-tooltip="actionHelpText[element.id]"
v-b-tooltip.hover :title="actionHelpText[element.id]"
>
<i class="bi bi-question-lg"></i>
</button>
@@ -470,7 +469,6 @@ import { unwrap } from "./util/unwrap";
import { convertFormData } from "./util/convertFormData";
import axios from "axios";
import { NPCPriorityBtnHelpMessage } from "./helpTexts";
import { CTooltip } from "@coreui/vue/src/directives/CTooltip";
import draggable from "vuedraggable";
import MyToast from "./components/MyToast.vue";
import TopBackBar from "./components/TopBackBar.vue";
@@ -512,9 +510,6 @@ export default defineComponent({
draggable,
MyToast,
},
directives: {
"c-tooltip": CTooltip,
},
methods: {
resetPolicy() {
if (!confirm("초기 설정으로 되돌릴까요?")) {
+6 -5
View File
@@ -1,3 +1,4 @@
import { exportWindow } from './util/exportWindow';
import $ from 'jquery';
import Popper from 'popper.js';
exportWindow(Popper, 'Popper');//XXX: 왜 popper를 이렇게 불러야 하는가?
@@ -5,12 +6,12 @@ import 'bootstrap';
import download from 'downloadjs';
import { unwrap } from "./util/unwrap";
import { isInteger } from 'lodash';
import { combineArray, errUnknown, getNpcColor, isBrightColor } from './common_legacy';
import { combineArray, errUnknown, getNpcColor } from './common_legacy';
import { isBrightColor } from "./util/isBrightColor";
import { numberWithCommas } from "./util/numberWithCommas";
import { unwrap_any } from './util/unwrap_any';
import { BasicGeneralListResponse, InvalidResponse } from './defs';
import { formatTime } from './util/formatTime';
import { exportWindow } from './util/exportWindow';
type CityAttackerInfo = {
level: number,
@@ -892,7 +893,7 @@ $(function ($) {
}
showBattleResult(result);
}, function (result) {
}, function () {
alert('전투 개시 실패!');
});
}
@@ -932,7 +933,7 @@ $(function ($) {
}
reorderDefender(result.order);
}, function (result) {
}, function () {
alert('재정렬 실패!');
});
}
@@ -967,7 +968,7 @@ $(function ($) {
});
$('#importModal').on('show.bs.modal', function (e) {
$('#importModal').on('show.bs.modal', function () {
if (!initGeneralList) {
const $list = $('#modalSelector');
+1 -1
View File
@@ -1,10 +1,10 @@
import { exportWindow } from './util/exportWindow';
import $ from 'jquery';
import axios from 'axios';
import { convertFormData } from './util/convertFormData';
import { InvalidResponse } from './defs';
import { unwrap_any } from './util/unwrap_any';
import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
import { exportWindow } from './util/exportWindow';
import Popper from 'popper.js';
exportWindow(Popper, 'Popper');
import 'bootstrap';
+4 -4
View File
@@ -1,7 +1,6 @@
{
"ingame": {
"chiefCenter": "chiefCenter.ts",
"common": "common_deprecated.ts",
"troop": "troop.ts",
"map": "map.ts",
"install_db": "install_db.ts",
@@ -20,13 +19,14 @@
"currentCity": "currentCity.ts",
"hallOfFame": "hallOfFame.ts",
"history": "history.ts",
"join": "join.ts",
"select_general_from_pool": "select_general_from_pool.ts",
"extKingdoms": "extKingdoms.ts"
"extKingdoms": "extKingdoms.ts",
"common": "common_deprecated.ts"
},
"ingame_vue": {
"v_inheritPoint": "v_inheritPoint.ts",
"v_board": "v_board.ts",
"v_NPCControl": "v_NPCControl.ts"
"v_NPCControl": "v_NPCControl.ts",
"v_join": "v_join.ts"
}
}
+4 -2
View File
@@ -1,10 +1,12 @@
import { activateFlip, isBrightColor, getIconPath, errUnknown, errUnknownToast, quickReject, initTooltip } from "./common_legacy";
import { exportWindow } from "./util/exportWindow";
import { activateFlip, errUnknown, errUnknownToast, quickReject, initTooltip } from "./common_legacy";
import { isBrightColor } from "./util/isBrightColor";
import { getIconPath } from "./util/getIconPath";
import { mb_strwidth } from "./util/mb_strwidth";
import { TemplateEngine } from "./util/TemplateEngine";
import { escapeHtml } from "./legacy/escapeHtml";
import { nl2br } from "./util/nl2br";
import jQuery from "jquery";
import { exportWindow } from "./util/exportWindow";
import Popper from 'popper.js';
exportWindow(Popper, 'Popper');//XXX: 왜 popper를 이렇게 불러야 하는가?
import 'bootstrap';
-28
View File
@@ -1,4 +1,3 @@
import { unwrap } from "./util/unwrap";
import $ from "jquery";
import axios from "axios";
@@ -31,24 +30,6 @@ export function stringFormat(text: string, ...args: (string | number)[]): string
});
}
export function hexToRgb(hex: string): { r: number, g: number, b: number } | null {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
export function isBrightColor(color: string): boolean {
const cv = unwrap(hexToRgb(color));
if ((cv.r * 0.299 + cv.g * 0.587 + cv.b * 0.114) > 140) {
return true;
} else {
return false;
}
}
/**
* color type만
* @param {string} color #AAAAAA AAAAAA RGB hex color string
@@ -82,15 +63,6 @@ declare global {
linkifyStr: (v: string, k?: Record<string, string | number>) => string;
}
}
export function getIconPath(imgsvr: boolean | 1 | 0, picture: string): string {
// ../d_shared/common_path.js 필요
if (!imgsvr) {
return window.pathConfig.sharedIcon + '/' + picture;
} else {
return window.pathConfig.root + '/d_pic/' + picture;
}
}
export function activateFlip($obj?: JQuery<HTMLElement>): void {
let $result: JQuery<HTMLElement>;
if ($obj === undefined) {
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<table style="width: 1000px; margin: auto" class="tb_layout bg0">
<table style="width: 1000px; margin: auto" class="bg0">
<tr>
<td style="text-align: left">
{{title}}<br /><button
+19 -1
View File
@@ -1,6 +1,6 @@
<template>
<div class="row form-group number-input-with-info">
<label class="col-6 col-form-label">{{ title }}</label>
<label v-if="!right" class="col-6 col-form-label">{{ title }}</label>
<div class="col-6">
<input
ref="input"
@@ -17,11 +17,13 @@
<input
type="text"
class="form-control"
:readonly="readonly"
:value="printValue"
@focus="onFocusText"
:style="{ display: !editmode ? undefined : 'none' }"
/>
</div>
<label v-if="right" class="col-6 col-form-label">{{ title }}</label>
</div>
<div style="text-align: right">
<small class="form-text text-muted"><slot></slot></small>
@@ -33,6 +35,11 @@ import { defineComponent } from "vue";
export default defineComponent({
name: "NumberInputWithInfo",
props: {
readonly: {
type: Boolean,
required: false,
default: false,
},
int: {
type: Boolean,
required: false,
@@ -59,6 +66,11 @@ export default defineComponent({
type: Number,
default: 0,
},
right: {
type: Boolean,
required: false,
default: false,
}
},
emits: ["update:modelValue"],
data() {
@@ -76,6 +88,9 @@ export default defineComponent({
},
methods: {
updateValue() {
if(this.readonly){
return;
}
if (this.int) {
this.rawValue = Math.floor(this.rawValue);
}
@@ -87,6 +102,9 @@ export default defineComponent({
this.printValue = this.rawValue.toLocaleString();
},
onFocusText() {
if(this.readonly){
return;
}
this.editmode = true;
setTimeout(() => {
(this.$refs.input as HTMLInputElement).focus();
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div class="tb_layout bg0 back_bar">
<div class="bg0 back_bar">
<button type="button" class="btn btn-primary back_btn" @click="back">
돌아가기
</button>
+1 -1
View File
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { unwrap_any } from './util/unwrap_any';
import axios from 'axios';
import { isBrightColor } from './common_legacy';
import { isBrightColor } from "./util/isBrightColor";
import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
import { isString } from 'lodash';
import { convertFormData } from './util/convertFormData';
+2
View File
@@ -1,5 +1,7 @@
import axios from 'axios';
import $ from 'jquery';
import Popper from 'popper.js';
exportWindow(Popper, 'Popper');//XXX: 왜 popper를 이렇게 불러야 하는가?
import { isNumber } from 'lodash';
import { TemplateEngine } from '../util/TemplateEngine';
import { InvalidResponse } from '../defs';
+6 -11
View File
@@ -1,5 +1,4 @@
import $ from 'jquery';
import { exportWindow } from '../util/exportWindow';
import axios from 'axios';
import { setAxiosXMLHttpRequest } from '../util/setAxiosXMLHttpRequest';
import { InvalidResponse } from '../defs';
@@ -65,10 +64,6 @@ const serverAdminTemplate = '\
declare global {
interface Window {
modifyServerStatus: (caller: HTMLElement, action: string) => void;
Entrance_AdminClosedLogin: (caller: HTMLElement) => void;
Entrance_AdminOpen119: (caller: HTMLElement) => void;
serverUpdate: (caller: HTMLElement) => void;
adminGrade: number;
aclList: Record<string, string[]>;
}
@@ -218,11 +213,6 @@ export async function loadPlugin(): Promise<void> {
Entrance_AdminInit();
window.modifyServerStatus = modifyServerStatus;
window.Entrance_AdminClosedLogin = Entrance_AdminClosedLogin;
window.Entrance_AdminOpen119 = Entrance_AdminOpen119;
window.serverUpdate = serverUpdate;
const response = await axios({
url: 'j_server_get_admin_status.php',
method: 'post',
@@ -330,3 +320,8 @@ function Entrance_AdminOpen119(caller: HTMLElement) {
const serverDir = $caller.parents('tr').data('server_name');
location.href = `../${serverDir}/_119.php`;
}
exportWindow(modifyServerStatus, 'modifyServerStatus');
exportWindow(Entrance_AdminClosedLogin, 'Entrance_AdminClosedLogin');
exportWindow(Entrance_AdminOpen119, 'Entrance_AdminOpen119');
exportWindow(serverUpdate, 'serverUpdate');
-1
View File
@@ -1 +0,0 @@
export * from '../common_deprecated';
+17 -3
View File
@@ -1,5 +1,10 @@
import axios from 'axios';
import { exportWindow } from '../util/exportWindow';
import $ from 'jquery';
exportWindow($, '$');
import Popper from 'popper.js';
exportWindow(Popper, 'Popper');//XXX: 왜 popper를 이렇게 불러야 하는가?
import axios from 'axios';
import 'bootstrap';
import { initTooltip } from '../common_legacy';
import { TemplateEngine } from "../util/TemplateEngine";
import { InvalidResponse } from '../defs';
@@ -7,6 +12,7 @@ import { getDateTimeNow } from '../util/getDateTimeNow';
import { setAxiosXMLHttpRequest } from '../util/setAxiosXMLHttpRequest';
import { loadPlugin as loadAdminPlugin } from './admin_server';
declare const isAdmin: boolean;
const serverListTemplate = "\
@@ -55,7 +61,7 @@ const serverLoginBtn = "<a href='<%serverPath%>/' class='item'\
></a>";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const serverCreateBtn = "<a href='<%serverPath%>/join.php' class='item'\
const serverCreateBtn = "<a href='<%serverPath%>/v_join.php' class='item'\
><button type='button' class='fill_box with_skin'></button\
></a>";
@@ -73,7 +79,7 @@ const serverCreateTemplate = "\
<td colspan='2' class='not_registered'>- -</div>\
<td class='ignore_border vertical_flex BtnPlate'>\
<%if(canCreate) {%>\
<a href='<%serverPath%>/join.php' class='item'><button type='button' class='fill_box with_skin'></button></a>\
<a href='<%serverPath%>/v_join.php' class='item'><button type='button' class='fill_box with_skin'></button></a>\
<%}%>\
<%if(canSelectNPC) {%>\
<a href='<%serverPath%>/select_npc.php' class='item'><button type='button' class='fill_box with_skin'></button></a>\
@@ -236,6 +242,14 @@ async function Entrance_drawServerList(serverInfos: ServerResponseItem[]) {
continue;
}
if(response.reserved){
$serverHtml.find('.server_down').detach();
$serverHtml.append(
TemplateEngine(serverReservedTemplate, response.reserved)
);
initTooltip($serverHtml);
}
if(!response.game){
continue;
}
+2 -3
View File
@@ -1,5 +1,4 @@
import { template } from "lodash";
import { NationPolicy, NPCChiefActions, NPCGeneralActions } from "./defs";
import { NPCChiefActions, NPCGeneralActions } from "./defs";
export const NPCPriorityBtnHelpMessage: {
[v in NPCChiefActions | NPCGeneralActions]: string;
@@ -34,7 +33,7 @@ export const NPCPriorityBtnHelpMessage: {
NPC후방발령:
"NPC전투장 중에<br>- 병력이 충분하지 않고,<br>- 도시의 인구가 제자리 징병할 수 있을 정도로 충분하지 않고,<br>- 부대에 탑승하지 않았다면,<br>인구가 충분한 후방도시로 발령합니다.",
NPC포상:
"금/쌀이 부족한 유저장에게 포상합니다.<br>NPC전투장과 NPC내정장은 각각 기준을 따릅니다.<br>국고 권장량을 가급적 지킵니다.",
"금/쌀이 부족한 NPC에게 포상합니다.<br>NPC전투장과 NPC내정장은 각각 기준을 따릅니다.<br>국고 권장량을 가급적 지킵니다.",
NPC전방발령:
"후방에 있는 유저장이<br>- 병력을 가지고 있으며,<br>- 곧 훈련/사기진작이 완료될 것 같으면,<br>전방으로 발령합니다.<br><br>도시 관직이 많이 임명된 도시를 선호합니다.",
:
+556 -9
View File
@@ -2,19 +2,27 @@
<top-back-bar :title="title" />
<div
id="container"
class="tb_layout bg0"
style="width: 1000px; margin: auto; border: solid 1px #888888"
class="bg0 px-2"
style="
max-width: 1000px;
margin: auto;
border: solid 1px #888888;
overflow: hidden;
"
>
<div id="inheritance_list">
<div id="inheritance_list" class="row">
<template v-for="(text, key) in inheritanceViewText" :key="key">
<div :id="`inherit_${key}`" class="inherit_item inherit_template_item">
<div
:id="`inherit_${key}`"
class="col col-sm-4 col-12 inherit_item inherit_template_item"
>
<div class="row">
<label
:id="`inherit_${key}_head`"
class="inherit_head col-sm-6 col-form-label"
class="inherit_head col col-md-6 col-sm-7 col-6 col-form-label"
>{{ text.title }}</label
>
<div class="col-sm-6">
<div class="col col-md-6 col-sm-5 col-6">
<input
type="text"
class="form-control inherit_value"
@@ -34,17 +42,230 @@
</div>
</template>
</div>
<div id="inheritance_store">
<div class="row">
<div class="col"><div class="bg1 a-center">유산 포인트 상점</div></div>
</div>
<div class="row">
<div class="col offset-md-4 col-md-4 col-sm-6 col-12 py-2">
<div class="row px-4">
<div class="a-right col-6 align-self-center">
다음 전투 특기 선택
</div>
<div class="col-6">
<select class="form-select col-6" v-model="nextSpecialWar">
<option
v-for="(info, key) in availableSpecialWar"
:key="key"
:value="key"
>
{{ info.title }}
</option>
</select>
</div>
</div>
<div class="a-right">
<small class="form-text text-muted"
><span
style="color: white"
v-html="availableSpecialWar[nextSpecialWar].info"
/><br />다음에 얻을 전투 특기를 정합니다.<br /><span
style="color: white"
>필요 포인트: {{ inheritActionCost.nextSpecial }}</span
></small
>
</div>
<div class="row px-4">
<b-button
class="col-6 offset-6"
variant="primary"
@click="setNextSpecialWar"
>구입</b-button
>
</div>
</div>
<div class="col col-md-4 col-sm-6 col-12 py-2">
<div class="row px-4">
<div class="a-right col-6 align-self-center">유니크 입찰</div>
<div class="col-6">
<select class="form-select col-6" v-model="specificUnique">
<option
v-for="(info, key) in availableUnique"
:key="key"
:value="key"
>
{{ info.title }}
</option>
</select>
</div>
</div>
<div class="row px-4">
<div class="col">
<NumberInputWithInfo
title="입찰 포인트"
:min="inheritActionCost.minSpecificUnique"
:max="this.items.previous"
v-model="specificUniqueAmount"
/>
</div>
</div>
<div class="a-right">
<small class="form-text text-muted"
>얻고자 하는 유니크 아이템을 포인트를 걸어 입찰합니다. 최고
포인트인 경우 다음 턴에 유니크를 얻습니다.<br /><span
style="color: white"
v-html="availableUnique[specificUnique].info"
/></small>
</div>
<div class="row px-4">
<b-button
class="col-6 offset-6"
variant="primary"
@click="buySpecificUnique"
>구입</b-button
>
</div>
</div>
</div>
<div style="width: 100%; padding: 0 10px">
<hr :style="{ opacity: 0.5 }" />
</div>
<div class="row py-sm-2">
<div class="col col-md-4 col-sm-6 col-12 py-2">
<div class="row px-4">
<div class="a-right col-6 align-self-center">랜덤 초기화</div>
<b-button
class="col-6"
variant="primary"
@click="buySimple('ResetTurnTime')"
>구입</b-button
>
</div>
<div class="a-right">
<small class="form-text text-muted"
>다음 턴이 랜덤으로 바뀝니다.<br /><span style="color: white"
>필요 포인트: {{ inheritActionCost.resetTurnTime }}</span
></small
>
</div>
</div>
<div class="col col-md-4 col-sm-6 col-12 py-2">
<div class="row px-4">
<div class="a-right col-6 align-self-center">랜덤 유니크 획득</div>
<b-button
class="col-6"
variant="primary"
@click="buySimple('BuyRandomUnique')"
>구입</b-button
>
</div>
<div class="a-right">
<small class="form-text text-muted"
>다음 턴에 랜덤 유니크를 얻습니다.<br /><span style="color: white"
>필요 포인트: {{ inheritActionCost.randomUnique }}</span
></small
>
</div>
</div>
<div class="col col-md-4 col-sm-6 col-12 py-2">
<div class="row px-4">
<div class="a-right col-6 align-self-center">
즉시 전투 특기 초기화
</div>
<b-button
class="col-6"
variant="primary"
@click="buySimple('ResetSpecialWar')"
>구입</b-button
>
</div>
<div class="a-right">
<small class="form-text text-muted"
>즉시 전투 특기를 초기화합니다.<br /><span style="color: white"
>필요 포인트: {{ inheritActionCost.resetSpecialWar }}</span
></small
>
</div>
</div>
</div>
</div>
<div style="width: 100%; padding: 0 10px">
<hr :style="{ opacity: 0.5 }" />
</div>
<div class="row">
<div
class="col col-md-4 col-sm-6 col-12"
v-for="(info, buffKey) in inheritBuffHelpText"
:key="buffKey"
>
<div class="row">
<label class="col col-sm-6 col-form-label" :for="`buff-${buffKey}`">{{
info.title
}}</label>
<div class="col col-sm-6">
<b-form-input
:id="`buff-${buffKey}`"
type="number"
v-model="inheritBuff[buffKey]"
:min="prevInheritBuff[buffKey] ?? 0"
:max="maxInheritBuff"
></b-form-input>
</div>
</div>
<div style="text-align: right">
<small class="form-text text-muted"
>{{ info.info }}<br /><span style="color: white"
>필요 포인트:
{{
inheritActionCost.buff[inheritBuff[buffKey]] -
inheritActionCost.buff[prevInheritBuff[buffKey] ?? 0]
}}</span
></small
>
</div>
<div class="row px-4" style="margin-bottom: 1em">
<b-button
variant="secondary"
@click="inheritBuff[buffKey] = prevInheritBuff[buffKey] ?? 0"
class="col col-md-6 col-4 offset-md-0 offset-4"
>리셋</b-button
><b-button
variant="primary"
class="col col-md-6 col-4"
@click="buyInheritBuff(buffKey)"
>구입</b-button
>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="bg1 a-center">유산 포인트 변경 내역(최근 30)</div>
</div>
</div>
<div class="row" v-for="(log, idx) in lastInheritPointLogs" :key="idx">
<div class="col a-right" style="max-width:20ch">
<small class="text-muted">[{{log.date}}]</small>
</div>
<div class="col a-left">
{{log.text}}
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue";
import { defineComponent } from "vue";
import "../scss/bootstrap5.scss";
import "../scss/inheritPoint.scss";
import "../scss/game_bg.scss";
import TopBackBar from "./components/TopBackBar.vue";
import { sum } from "lodash";
import _ from "lodash";
import { InvalidResponse } from "./defs";
import axios from "axios";
import NumberInputWithInfo from "./components/NumberInputWithInfo.vue";
type InheritanceType =
| "previous"
@@ -61,6 +282,14 @@ type InheritanceType =
type InheritanceViewType = InheritanceType | "sum" | "new";
declare const lastInheritPointLogs: {
server_id: string,
year: number,
month: number,
date: string,
text: string,
}[];
declare const items: Record<InheritanceType, number>;
const inheritanceViewText: Record<
@@ -121,9 +350,99 @@ const inheritanceViewText: Record<
},
};
type inheritBuffType =
| "warAvoidRatio"
| "warCriticalRatio"
| "warMagicTrialProb"
| "domesticSuccessProb"
| "domesticFailProb"
| "warAvoidRatioOppose"
| "warCriticalRatioOppose"
| "warMagicTrialProbOppose";
declare const currentInheritBuff: {
[v in inheritBuffType]: number | undefined;
};
const inheritBuffHelpText: Record<
inheritBuffType,
{
title: string;
info: string;
}
> = {
warAvoidRatio: {
title: "회피 확률 증가",
info: "전투 시 회피 확률이 1%p ~ 5%p 증가합니다.",
},
warCriticalRatio: {
title: "필살 확률 증가",
info: "전투 시 필살 확률이 1%p ~ 5%p 증가합니다.",
},
warMagicTrialProb: {
title: "계략 시도 확률 증가",
info: "전투 시 계략을 시도할 확률이 1%p ~ 5%p 증가합니다. 무장도 계략을 시도합니다.",
},
warAvoidRatioOppose: {
title: "상대 회피 확률 감소",
info: "전투 시 상대의 회피 확률이 1%p ~ 5%p 감소합니다.",
},
warCriticalRatioOppose: {
title: "상대 필살 확률 감소",
info: "전투 시 상대의 필살 확률이 1%p ~ 5%p 감소합니다.",
},
warMagicTrialProbOppose: {
title: "상대 계략 시도 확률 감소",
info: "전투 시 상대의 계략 시도 확률이 1%p ~ 5%p 감소합니다.",
},
domesticSuccessProb: {
title: "내정 성공 확률 증가",
info: "민심, 인구, 농업, 상업, 치안, 수비, 성벽, 기술 내정의 성공 확률이 1%p ~ 5%p 증가합니다.",
},
domesticFailProb: {
title: "내정 실패 확률 감소",
info: "민심, 인구, 농업, 상업, 치안, 수비, 성벽, 기술 내정의 실패 확률이 1%p ~ 5%p 감소합니다.",
},
};
declare const maxInheritBuff: number;
declare const inheritActionCost: {
buff: number[];
resetTurnTime: number;
resetSpecialWar: number;
randomUnique: number;
nextSpecial: number;
minSpecificUnique: number;
};
declare const resetTurnTimeLevel: number;
declare const resetSpecialWarLevel: number;
declare const availableSpecialWar: Record<
string,
{
title: string;
info: string;
}
>;
declare const availableUnique: Record<
string,
{
title: string;
info: string;
}
>;
export default defineComponent({
name: "InheritPoint",
data() {
const inheritBuff = {} as Record<inheritBuffType, number>;
for (const buffKey of Object.keys(
inheritBuffHelpText
) as inheritBuffType[]) {
inheritBuff[buffKey] = currentInheritBuff[buffKey] ?? 0;
}
return {
title: "유산 관리",
inheritanceViewText,
@@ -138,14 +457,242 @@ export default defineComponent({
};
return result;
})(),
inheritBuffHelpText,
inheritBuff,
prevInheritBuff: currentInheritBuff,
maxInheritBuff,
inheritActionCost,
resetTurnTimeLevel,
resetSpecialWarLevel,
nextSpecialWar: Object.keys(availableSpecialWar)[0],
specificUnique: Object.keys(availableUnique)[0],
availableSpecialWar,
availableUnique,
specificUniqueAmount: inheritActionCost.minSpecificUnique,
lastInheritPointLogs,
};
},
methods: {
async buyInheritBuff(buffKey: inheritBuffType) {
const level = this.inheritBuff[buffKey];
const prevLevel = this.prevInheritBuff[buffKey] ?? 0;
if (level == prevLevel) {
return;
}
if (level < prevLevel) {
alert("낮출 수 없습니다.");
return;
}
const cost =
this.inheritActionCost.buff[level] -
this.inheritActionCost.buff[prevLevel];
if (this.items.previous < cost) {
alert("유산 포인트가 부족합니다.");
return;
}
const name = inheritBuffHelpText[buffKey].title;
if (
!confirm(
`${name}${level}등급으로 올릴까요? ${cost} 포인트가 소모됩니다.`
)
) {
return;
}
let result: InvalidResponse;
try {
const response = await axios({
url: "api.php",
method: "post",
responseType: "json",
data: {
path: "InheritAction/BuyHiddenBuff",
args: {
type: buffKey,
level,
},
},
});
result = response.data;
if (!result.result) {
throw result.reason;
}
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
alert("성공했습니다.");
//TODO:
location.reload();
},
async buySimple(
type: "ResetTurnTime" | "BuyRandomUnique" | "ResetSpecialWar"
) {
const costMap: Record<typeof type, number> = {
ResetTurnTime: inheritActionCost.resetTurnTime,
ResetSpecialWar: inheritActionCost.resetSpecialWar,
BuyRandomUnique: inheritActionCost.randomUnique,
};
const cost = costMap[type];
if (cost === undefined) {
alert(`올바르지 않은 타입:${type}`);
return;
}
const messageMap: Record<typeof type, string> = {
ResetTurnTime: `${cost} 포인트로 턴을 초기화 하시겠습니까?`,
ResetSpecialWar: `${cost} 포인트로 전투 특기를 초기화 하시겠습니까?`,
BuyRandomUnique: `${cost} 포인트로 랜덤 유니크를 구입하시겠습니까?`,
};
if (this.items.previous < cost) {
alert("유산 포인트가 부족합니다.");
return;
}
if (!confirm(messageMap[type])) {
return;
}
let result: InvalidResponse;
try {
const response = await axios({
url: "api.php",
method: "post",
responseType: "json",
data: {
path: `InheritAction/${type}`,
args: {},
},
});
result = response.data;
if (!result.result) {
throw result.reason;
}
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
alert("성공했습니다.");
//TODO:
location.reload();
},
async setNextSpecialWar() {
const specialWarName =
this.availableSpecialWar[this.nextSpecialWar].title ?? undefined;
if (specialWarName === undefined) {
alert(`잘못된 타입: ${this.nextSpecialWar}`);
return;
}
const cost = inheritActionCost.nextSpecial;
if (this.items.previous < cost) {
alert("유산 포인트가 부족합니다.");
return;
}
//TODO: JosaUtil
if (
!confirm(
`${cost} 포인트로 다음 전특을 ${specialWarName}(으)로 고정하겠습니까?`
)
) {
return;
}
let result: InvalidResponse;
try {
const response = await axios({
url: "api.php",
method: "post",
responseType: "json",
data: {
path: `InheritAction/SetNextSpecialWar`,
args: {
type: this.nextSpecialWar,
},
},
});
result = response.data;
if (!result.result) {
throw result.reason;
}
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
alert("성공했습니다.");
//TODO:
location.reload();
},
async buySpecificUnique() {
const uniqueName =
this.availableUnique[this.specificUnique].title ?? undefined;
if (uniqueName === undefined) {
alert(`잘못된 타입: ${this.specificUnique}`);
return;
}
const amount = this.specificUniqueAmount;
if (this.items.previous < amount) {
alert("유산 포인트가 부족합니다.");
return;
}
//TODO: JosaUtil
if (!confirm(`${amount} 포인트로 ${uniqueName}(을)를 입찰하겠습니까?`)) {
return;
}
let result: InvalidResponse;
try {
const response = await axios({
url: "api.php",
method: "post",
responseType: "json",
data: {
path: `InheritAction/BuySpecificUnique`,
args: {
item: this.specificUnique,
amount,
},
},
});
result = response.data;
if (!result.result) {
throw result.reason;
}
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
alert("성공했습니다.");
//TODO:
location.reload();
},
},
components: {
TopBackBar,
NumberInputWithInfo,
},
});
</script>
<style>
.col-form-label {
text-align: right;
padding-right: 2ch;
}
.inherit_value {
text-align: right;
}
</style>
-213
View File
@@ -1,213 +0,0 @@
import $ from 'jquery';
import { exportWindow } from './util/exportWindow';
import { mb_strwidth } from './util/mb_strwidth';
import { unwrap_any } from './util/unwrap_any';
declare const defaultStatTotal: number;
declare const defaultStatMax: number;
declare const defaultStatMin: number;
declare const charInfoText: Record<string, string>;
$(function ($) {
const $leadership = $('#leadership');
const $strength = $('#strength');
const $intel = $('#intel');
function abilityRand(): void {
let leadership = Math.random() * 65 + 10;
let strength = Math.random() * 65 + 10;
let intel = Math.random() * 65 + 10;
const rate = leadership + strength + intel;
leadership = Math.floor(leadership / rate * defaultStatTotal);
strength = Math.floor(strength / rate * defaultStatTotal);
intel = Math.floor(intel / rate * defaultStatTotal);
while (leadership + strength + intel < defaultStatTotal) {
leadership += 1;
}
if (leadership > defaultStatMax || strength > defaultStatMax || intel > defaultStatMax || leadership < defaultStatMin || strength < defaultStatMin || intel < defaultStatMin) {
return abilityRand();
}
$leadership.val(leadership);
$strength.val(strength);
$intel.val(intel);
}
function abilityLeadpow() {
let leadership = Math.random() * 6;
let strength = Math.random() * 6;
let intel = Math.random() * 1;
const rate = leadership + strength + intel;
leadership = Math.floor(leadership / rate * defaultStatTotal);
strength = Math.floor(strength / rate * defaultStatTotal);
intel = Math.floor(intel / rate * defaultStatTotal);
while (leadership + strength + intel < defaultStatTotal) {
strength += 1;
}
if (intel < defaultStatMin) {
leadership -= defaultStatMin - intel;
intel = defaultStatMin;
}
if (leadership > defaultStatMax) {
strength += leadership - defaultStatMax;
leadership = defaultStatMax;
}
if (strength > defaultStatMax) {
leadership += strength - defaultStatMax;
strength = defaultStatMax;
}
if (leadership > defaultStatMax) {
intel += leadership - defaultStatMax;
leadership = defaultStatMax;
}
$leadership.val(leadership);
$strength.val(strength);
$intel.val(intel);
}
function abilityLeadint() {
let leadership = Math.random() * 6;
let strength = Math.random() * 1;
let intel = Math.random() * 6;
const rate = leadership + strength + intel;
leadership = Math.floor(leadership / rate * defaultStatTotal);
strength = Math.floor(strength / rate * defaultStatTotal);
intel = Math.floor(intel / rate * defaultStatTotal);
while (leadership + strength + intel < defaultStatTotal) {
intel += 1;
}
if (strength < defaultStatMin) {
leadership -= defaultStatMin - strength;
strength = defaultStatMin;
}
if (leadership > defaultStatMax) {
intel += leadership - defaultStatMax;
leadership = defaultStatMax;
}
if (intel > defaultStatMax) {
leadership += intel - defaultStatMax;
intel = defaultStatMax;
}
if (leadership > defaultStatMax) {
strength += leadership - defaultStatMax;
leadership = defaultStatMax;
}
$leadership.val(leadership);
$strength.val(strength);
$intel.val(intel);
}
function abilityPowint() {
let leadership = Math.random() * 1;
let strength = Math.random() * 6;
let intel = Math.random() * 6;
const rate = leadership + strength + intel;
leadership = Math.floor(leadership / rate * defaultStatTotal);
strength = Math.floor(strength / rate * defaultStatTotal);
intel = Math.floor(intel / rate * defaultStatTotal);
while (leadership + strength + intel < defaultStatTotal) {
intel += 1;
}
if (leadership < defaultStatMin) {
strength -= defaultStatMin - leadership;
leadership = defaultStatMin;
}
if (strength > defaultStatMax) {
intel += strength - defaultStatMax;
strength = defaultStatMax;
}
if (intel > defaultStatMax) {
strength += intel - defaultStatMax;
intel = defaultStatMax;
}
if (strength > defaultStatMax) {
leadership += strength - defaultStatMax;
strength = defaultStatMax;
}
$leadership.val(leadership);
$strength.val(strength);
$intel.val(intel);
}
exportWindow(abilityRand, 'abilityRand');
exportWindow(abilityLeadpow, 'abilityLeadpow');
exportWindow(abilityLeadint, 'abilityLeadint');
exportWindow(abilityPowint, 'abilityPowint');
const $charInfoText = $('#charInfoText');
const $selChar = $('#selChar');
$selChar.change(function () {
const $this = $(this);
const char = unwrap_any<string>($this.val());
if (char in charInfoText) {
$charInfoText.html(charInfoText[char]);
}
else {
$charInfoText.html('');
}
});
const $generalName = $('#generalName');
$generalName.on('change keyup paste', function () {
const generalName = unwrap_any<string>($generalName.val());
const len = mb_strwidth(generalName);
if (len == 0 || len > 18) {
$generalName.css('color', 'red');
}
else {
$generalName.css('color', 'white');
}
});
$('#join_form').submit(function () {
const generalName = unwrap_any<string>($generalName.val());
if (mb_strwidth(generalName) > 18) {
alert('장수 이름이 너무 깁니다!');
return false;
}
const currentStatTotal = parseInt(unwrap_any<string>($leadership.val())) + parseInt(unwrap_any<string>($strength.val())) + parseInt(unwrap_any<string>($intel.val()));
if (currentStatTotal < defaultStatTotal) {
if (!confirm(`현재 능력치 총합은 ${currentStatTotal}으로, ${defaultStatTotal}보다 낮습니다. 그래도 생성할까요?`)) {
return false;
}
}
return true;
});
const randomGenType = Math.floor(Math.random() * 7);
if (randomGenType < 3) {
abilityLeadpow();
}
else if (randomGenType < 6) {
abilityLeadint();
}
else {
abilityPowint();
}
});

Some files were not shown because too many files have changed in this diff Show More