Compare commits

...
367 Commits
Author SHA1 Message Date
Hide_D 4f40fa7813 misc: 턴 선택기 버튼 글씨 색 변경 2022-05-13 21:31:49 +09:00
Hide_D b7346b3816 misc: 턴 선택기의 주 버튼 색상 교체 2022-05-13 21:26:22 +09:00
Hide_D 400e47f616 fix: 토너먼트 베팅 시 최소 골드가 500이 아닌 버그 수정 2022-05-13 21:25:30 +09:00
Hide_D 5d499bbfbe fix: 서버 페이지에서 버튼을 bootstrap 버튼으로 변경 2022-05-13 20:27:31 +09:00
Hide_D e0d5c44184 fix: 아이템 버리기시, 조사 틀림 2022-05-13 18:01:31 +09:00
Hide_D f100998800 feat: 게임 시작 후, 거병/건국 기간, 출병 제한 기간을 안내 2022-05-11 02:22:40 +09:00
Hide_D 5bc31c91fa feat: 중원 정세에 메시지를 출력하는 Event Action 추가 2022-05-11 01:58:12 +09:00
Hide_D 4ca929d47d feat: 시작년도 기준으로 연월을 처리하는 Date Condition 추가 2022-05-11 01:50:05 +09:00
Hide_D 4ba43ea76a game: 기병의 출병시 병력 대상 전투력 5% 상향 2022-05-11 01:42:44 +09:00
Hide_D 34232a5504 game: 저지 발동시 숙련에 더해 명성도 추가 2022-05-11 01:36:54 +09:00
Hide_D 9b7464ab69 game: 필살 전투 특기가 '항상 최대 필살 대미지 계수'를 갖도록 수정
- 1.3 ~ 2.0에서 2.0 고정
2022-05-11 01:35:21 +09:00
Hide_D f003f38f74 fix: 일부 자동 조사가 적용되지 않는 코드 반영
- 유산 관리
  - 유니크 이름 받아오는 코드 일부 수정
- 인사부
2022-05-11 00:42:17 +09:00
Hide_D 91b2cecb19 feat: 유니크 입찰 시 첫번째 칸을 '공란'으로 두기 2022-05-11 00:32:03 +09:00
Hide_D 8c11661fb4 fix: 천통시 명장 일람에 유상포인트 최종 계산을 누락한 버그 수정 2022-05-11 00:26:47 +09:00
Hide_D 9aabe0442d game: 이미 같은 부위에 유니크를 가지고 있다면 유산 입찰 금지
- 이미 입찰한 같은 부위 유니크는 반환
2022-05-11 00:12:57 +09:00
Hide_D b463720512 fix: 아이템 파기 시 판매가 정정 2022-05-10 23:59:58 +09:00
Hide_D 6bc7c67589 feat: 장비매매로 유니크 판매시 전체 알림 2022-05-10 23:50:32 +09:00
Hide_D 443543d70f feat: 아이템 파기 추가 2022-05-10 23:46:39 +09:00
Hide_D 46a94b7816 feat: 명장 일람에 유산 소모량, 획득량 표기 2022-05-10 03:31:48 +09:00
Hide_D b2e297bbb3 feat: 유산 포인트 획득, 소모 정도를 동적으로 명장 일람 항목으로 기록
- 1월, 7월
- 베팅, 베팅 당첨을 소모/획득으로 분리
- 일단 유산 포인트 획득은 별도 분리
2022-05-10 03:26:34 +09:00
Hide_D 16906e960e feat: convertTupleArrayToDict 유틸리티 함수 생성 2022-05-10 02:37:50 +09:00
Hide_D 91bc734612 feat: 1, 7월마다 유산 포인트 rank_data 통계를 냄 2022-05-10 01:59:10 +09:00
Hide_D fa5546874a feat: RankColumn 유산 포인트 관련 추가 및 설명 보완 2022-05-09 23:58:15 +09:00
Hide_D 3921d159ef fix: 세력장수에서 rankColumn 대응 에러 수정 2022-05-09 22:33:16 +09:00
Hide_D cfcdc3149f fix: logExceptionByCustomHandler에서 echo 안하는 옵션 추가 2022-05-09 22:31:14 +09:00
Hide_D 717017fad5 misc: APIHelper에서 Exception과 Error를 상세 분리 2022-05-09 22:27:02 +09:00
Hide_D b8f957130d misc: 사용하지 않는 파일 제거 2022-05-09 22:02:54 +09:00
Hide_D 5824079b41 misc: 에러 로깅시 에러명에도 {ROOT}치환 2022-05-09 21:49:02 +09:00
Hide_D fbcfbb7156 fix: KVStorage deleteValue버그 수정 2022-05-09 21:42:17 +09:00
Hide_D b738984235 fix: 토너먼트 함수 인자에 맞게 수정 2022-05-09 21:40:20 +09:00
Hide_D c29333f8e0 fix: RankColumn 누락 부분 수정 2022-05-09 16:12:19 +09:00
Hide_D 123cf8d437 fix: error logger 수정 2022-05-09 16:08:53 +09:00
Hide_D 9293c4e480 feat: FatalError 대응 2022-05-09 03:42:51 +09:00
Hide_D fa5919aa1a Revert "refac: 에러 핸들링 방식 변경, FatalError 대응"
This reverts commit 80edfefdb1.
2022-05-09 03:40:54 +09:00
Hide_D 194f2bd2a5 refac: 에러 핸들링 방식 변경, FatalError 대응 2022-05-09 03:39:30 +09:00
Hide_D 0ae6584b02 fix: 아이템 치료의 우선순위가 낮아 '경상'치료가 안되는 버그 수정 2022-05-09 02:42:08 +09:00
Hide_D 397aa76e15 fix: KVStorage에서 Map으로 안 바뀐 코드 수정 2022-05-09 02:30:11 +09:00
Hide_D 43997b9117 fix: phan 메시지에 따라 수정
- array에 +=를 phan 알아듣기 쉽게 array_merge로
- Util::array_get이 더 이상 필요없으므로 null coalescing
- array로 tuple류를 반환하는 함수에 index를 포함하도록 변경
  - php intelephense에게는 현재 무효
- getPost 일부 값에 int 지정
- 아이템에 id property를 없앴으므로 관련 코드 제거
- enum은 array key로 사용할 수 없으므로 \Ds\Map으로 변경
- KakaoKey PhanRedefineClass 에러 우회
2022-05-09 01:25:12 +09:00
Hide_D de5fe818e6 fix: phan 출력 결과에 따라 처리
- switch에 변수를 정하는 경우 default에 throw
- Util::getPost에 일부 타입 강제
- array인 일부 값들에 PHPDoc 타입 지정
- Enum에 toString이 없으므로 value값 지정
- 사용하지 않는 use function 제거
2022-05-09 00:06:41 +09:00
Hide_D e3e315a068 dep: phan 2022-05-08 23:20:55 +09:00
Hide_D 5430a43589 fix: RankColumn 누락부분 수정 2022-05-08 23:11:15 +09:00
Hide_D a44172f509 refac: RankColumn enum 추가, General의 명장 일람 타입 변경 2022-05-08 23:09:27 +09:00
Hide_D 94bfd79afa fix: 감춰진 KVStorage의 initializer를 사용하는 코드 수정 2022-05-08 20:20:09 +09:00
Hide_D 2b4de68f0a refac: 더는 필요없어진 betting table 삭제 2022-05-08 20:15:03 +09:00
Hide_D 282b413553 refac: InheritPointManager를 Ds\Map으로 변경 2022-05-08 20:11:38 +09:00
Hide_D 5164585360 refac: KVStorage의 내부구조를 Ds\Map으로 변경 2022-05-08 20:10:04 +09:00
Hide_D f6642ecb0f dep: add php-ds 2022-05-08 19:23:24 +09:00
Hide_D 928042d71b feat: KVStorage에서 BackedEnum 지원 2022-05-08 13:30:16 +09:00
Hide_D 91cb3c4344 fix: 오타 수정 2022-05-08 13:15:28 +09:00
Hide_D eff79c4778 refac: 유산 포인트 파트를 별도의 Manager로 분리, enum 적용 2022-05-08 04:40:36 +09:00
Hide_D f7776d5067 dep: bootstrap5 warning 관련 버전 조정 2022-05-08 01:50:19 +09:00
Hide_D 68aae0bec1 misc: warning 제거 2022-05-08 01:44:16 +09:00
Hide_D cb7eb3b711 dep: package-updates 2022-05-08 01:36:06 +09:00
Hide_D 2a6b661285 fix: 연속 내정 성공 등, setInheritancePoint에 빙읮장을 누락한 버그 2022-05-07 15:26:52 +09:00
Hide_D d2ebf94453 fix: 빙의장이 베팅한 경우 베팅 성공으로 반영되지 않는 버그 수정 2022-05-07 15:24:16 +09:00
Hide_D 707f9ba7ce misc: 가입시 닉네임 변경 어려움을 알림 2022-05-07 15:16:38 +09:00
Hide_D 72e1d5e03b fix: 실제 코드 변경에 따라 의술을 1/3가 아니라 30%로 정정 2022-04-28 00:54:34 +09:00
Hide_D a612074aa4 fix: span, br 대신 div 2022-04-27 23:13:51 +09:00
Hide_D 86bbccb7f9 fix: 지도 렌더러에서 tooltip width가 덜 변경되도록 수정 2022-04-27 23:04:22 +09:00
Hide_D 11b7b57343 refac,feat: Global/ExecuteEngine
- 턴 실행
- 기존 proc.php와 유사
- 변경된 턴 있음 알림
2022-04-27 02:43:04 +09:00
Hide_D b682e53abe feat: General|Nation/GetGeneralLog 감찰부&내정보 로그 2022-04-27 01:40:09 +09:00
Hide_D ce877834cd feat: 장수 추가정보 카드
- 막대 구현
- 기존의 추가정보에 5턴분량 예턴 표기
2022-04-27 00:09:25 +09:00
Hide_D c69d171c3a feat: Nation/GeneralList 값 확장, 감찰부 2022-04-27 00:03:33 +09:00
Hide_D 1b24aa2421 feat: 기본 내정보 카드
- 아직 bar가 없음
2022-04-26 03:23:13 +09:00
Hide_D c61a4a70fc feat: Nation/GeneralList에 장수 기본 자료 일부 추가
- 내 정보, 감찰부에서 사용하는 자료
2022-04-26 03:14:48 +09:00
Hide_D bdefcc622f fix: Nation/GeneralList 권한 조정 2022-04-26 03:11:22 +09:00
Hide_D 67336323c2 fix: 세력장수에서 permission1(도시관직)도 보여야함. 2022-04-26 01:02:16 +09:00
Hide_D 3ac9e7c599 misc: 궁병 수비선제사격에서 선제 공격 로그를 단순하게 처리
- 상대방의 필살, 격노도 출력하지 않음
2022-04-26 00:39:36 +09:00
Hide_D 73f70fceff game,fix: 전추 치료 발동시 표기에 맞게 -50% -> -30% 2022-04-26 00:36:30 +09:00
Hide_D e353efc81d game: 궁병 수비 선제의 대미지를 50% 하향 2022-04-26 00:35:08 +09:00
Hide_D a37c427242 misc: auto500px, insertCustomCSS 누락된 페이지 정정 2022-04-26 00:33:54 +09:00
Hide_D d3c9b1f8a6 misc: 불필요한 베팅 import 코드 제거 2022-04-25 21:12:59 +09:00
Hide_D 0ca029babb fix: 천도 후 nationStaticInfo가 갱신되지 않는 버그 수정 2022-04-25 12:00:13 +09:00
Hide_D 492d113307 refac: 토너먼트 긴 switch 문을 assoc array로 변경 2022-04-25 02:33:37 +09:00
Hide_D f2bd48e452 fix,misc: 토너먼트 베팅 관련 잔여 코드 제거 2022-04-25 02:05:59 +09:00
Hide_D ddb7ee1ec2 fix: 국가 베팅장에서 '토너먼트'는 보여주지 않기로 2022-04-25 02:04:31 +09:00
Hide_D 7d62e94306 fix: 금 베팅시 betgold rankvar 누락 2022-04-25 01:51:42 +09:00
Hide_D 4961d76b96 fix: BettingDetail이 assocArray를 대응하지 못하는 버그 수정 2022-04-25 01:45:35 +09:00
Hide_D 12524e6e68 fix: 이제 BettingDetail 출력 변경
- BettingInfo의 candidate가 array를 보장하지 않음
- info가 html이 아니어도 출력
2022-04-25 01:30:54 +09:00
Hide_D 79f30ea275 refac: 토너먼트 베팅 세부 로직을 ng_betting으로 이동 (#218)
- 토너먼트 베팅을 betting 테이블 대신 Betting 모듈을 이용하는 형태로 변경
  - 이전 토너먼트 베팅 기록이 남음
  - 현재 이전 토너먼트 기록을 볼 수는 없음
- 베팅에 API/Betting/Bet 을 이용
- 토너먼트, 베팅 페이지를 Betting 모듈에 맞게 임시 조정
- 이전 버전과의 호환성을 위해 betting table과 betting 테이블에 초기값을 추가하는 로직은 남김
  - 이후 0.30이 되었을 때 제거

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/218
2022-04-25 01:06:32 +09:00
Hide_D 6ec2bf2880 fix: KVStorage에서 mb_strtolower를 제거하여 대소문자 구분 2022-04-25 00:39:13 +09:00
Hide_D 7708c26b71 refac: Betting 시작 코드를 모듈로 이동 2022-04-23 01:39:02 +09:00
Hide_D 4f300c6f82 refac: 구 jQuery Map wrapper를 Vue3 렌더러로 변경 2022-04-22 02:07:32 +09:00
Hide_D f4d67e759e refac: MapViewer에서 modelValue를 Legacy 버전과 맞춤 2022-04-22 00:36:25 +09:00
Hide_D e9b76217f7 feat: 임시용 cachedMap 출력 추가 2022-04-21 23:51:43 +09:00
Hide_D 85f801df4d feat: MapViewer와 API의 버전이 같을 때에만 지도 출력 2022-04-21 23:51:03 +09:00
Hide_D 01d5f2cda9 fix: 타 버전과 호환성을 위해, NO_SESSION 키워드 유지 2022-04-21 23:37:37 +09:00
Hide_D 601196e3f6 refac: APIHelper에 DummySession 적용, NO_LOGIN 구분 2022-04-21 23:33:08 +09:00
Hide_D cbf0be20a5 feat: SammoAPI 호출 prefix 변경 기능 제공 2022-04-21 23:17:23 +09:00
Hide_D e51421780e fix: 연감 철자 수정 2022-04-21 22:44:02 +09:00
Hide_D 2240282155 fix: 연감에서 폰트 크기 미 지정 2022-04-21 22:32:23 +09:00
Hide_D 5700b32c84 fix: 중원정보에서 분쟁 누락 2022-04-21 22:30:15 +09:00
Hide_D 4d72e0860e fix: AI에서 최근 전투 계산에서 외부 인력 계산 버그 2022-04-21 18:47:38 +09:00
Hide_D 994daf11d3 feat,refac: 중원 정보 페이지 2022-04-21 03:24:11 +09:00
Hide_D 79b92427aa fix: 중원정보 API에서 도시 목록이 id로 나오는 문제 2022-04-21 02:31:41 +09:00
Hide_D 6938c74014 feat: Global/GetDiplomacy 중원 정보 API 2022-04-21 02:28:17 +09:00
Hide_D 058a6e63f2 feat: Global/GetMap, Global/GetCachedMap 추가
-  지도를 가져오는 코드
- GetCahcedMap에서는 600초 단위 캐싱
  - history 필드에 최근 10건 표시
2022-04-21 01:24:07 +09:00
Hide_D 1be6b7a509 misc: Global/GetConst의 캐시 타입을 Public으로 변경 2022-04-21 01:18:12 +09:00
Hide_D ef532f0779 refac: API 캐시 컨트롤에서 max-age, public 지정 가능하도록 2022-04-21 01:17:20 +09:00
Hide_D 095a23df6d fix: get API의 경우 arg를 paramArg로 전환 2022-04-21 00:24:21 +09:00
Hide_D 7043521eaa fix: 연감 지도 수정 2022-04-20 22:40:07 +09:00
Hide_D 5eaafaeee6 fix: NPC 빙의 장수 목록 안보이는 버그 수정
- API/Global/GeneralList를 WithToken과 분리
2022-04-20 22:33:46 +09:00
Hide_D ec10949c64 fix: 걸그룹대전 스탯 수정 2022-04-20 21:56:31 +09:00
Hide_D 0e882cea17 feat: 걸그룹 대전 업데이트 2022-04-20 21:26:55 +09:00
Hide_D 4ad5cab37b feat,refac: vue3로 작성한 새 연감 페이지 (#217)
- 새 지도 렌더러 사용
- 새 연감 데이터 사용
- 500px 모드 지원
- Vue3 활용

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/217
2022-04-20 21:04:56 +09:00
Hide_D 2b6139050d feat: 커스터마이징 가능한 tooltip directive 2022-04-20 20:58:08 +09:00
Hide_D 14be16ce74 feat: Vue3로 작성된 지도 렌더러 (#216)
- 기존의 jQuery 기반 지도 렌더러를 Vue3로 재작성.
  - ajax로 호출하는 부분은 외부에서 처리하고, 다시 그리는 부분만 생성
  - 기능상으론 거의 동일.
- 일반 렌더러의 700px에, 500px모드용 모드 추가
  - 아이콘의 크기는 작아지지만, 글자 크기는 작아지지 않도록 조정

dep: vueuse, detect-it 추가

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/216
2022-04-20 03:34:12 +09:00
Hide_D c379ecf317 feat: 연감을 가져오는 API
- Global/GetHistory - 과거 기록. 캐싱 가능
- GetCurrentHistory - 현재 기록. 캐싱 불가
2022-04-18 03:05:08 +09:00
Hide_D eadbc774e3 misc: Global/GetConst session 모드 수정 2022-04-18 00:40:50 +09:00
Hide_D 90787cdc53 fix: 국가베팅 당첨자 없을 시, 버그 2022-04-17 21:40:24 +09:00
Hide_D 337733c3d3 fix,misc: 숙련 등급 입력시 음수인 경우에도 0으로 정상 처리 2022-04-17 21:19:35 +09:00
Hide_D b7048a4422 fix: NPC국 생성 시, 평균 기술력을 받아오지 못하는 문제 수정 2022-04-17 21:17:18 +09:00
Hide_D a036f1c4bb misc: 턴 선택기에서 커맨드 항목 높이를 조절 및 가운데 정렬 2022-04-15 20:11:21 +09:00
sars f9b1ab3ba7 배팅창에서 본선 장수들이 정해져있지 않을때 스탯을 출력하려는 워닝 수정 2022-04-14 19:17:40 -07:00
Hide_D 47599f000a refac: 명장일람, 명예의 전당 2022-04-15 02:36:42 +09:00
Hide_D efb1664443 refac: 감찰부 500px 모드 2022-04-15 02:00:51 +09:00
Hide_D 2c016621b6 game: 군주, 수뇌, 관직 전투력 상향 2022-04-14 01:28:44 +09:00
Hide_D f2a2b338cd fix: 전투 결과가 중복 기록되는 버그 수정 2022-04-13 03:05:23 +09:00
Hide_D 715a66fd35 fix: APIPathGen에서 NumVar, StrVar 동작 오류 2022-04-13 02:49:11 +09:00
Hide_D cc73f8c5d6 game: 베팅 포인트 수령 기준 변경
- 각 단계마다 총 수령액의 1/2씩, 잔여금은 1등상에게로
- 1등이 없는 경우 2등이 1등상+2등상 배분하여 수령
- 4개 선택시 각각, 56.25%, 25%, 12.5%, 6.25%를 나눠가짐
- 정답자가 전혀 없으면 포인트 환불
2022-04-13 02:33:58 +09:00
Hide_D 9b54b2b57d fix: 국가 베팅장에서 화면 이동 시에도 예전 기록이 남는 버그 수정 2022-04-13 02:04:00 +09:00
Hide_D fe4d095f21 game: 수뇌/관직 전투력 보정을 조정
- 수비시, 공격시가 아니라 항시 작동
- 군주: 공격 5%, 피해 -5%
- 참모: 공격 3%, 피해 -3%
- 무장 수뇌: 공격 3%
- 지장 수뇌: 피해 -3%
- 도시 관직: 공격 1.5%, 피해 -1.5%
2022-04-13 01:53:14 +09:00
Hide_D f67fa5c764 misc: JSON.parse 중 any인 것에 type 지정 2022-04-12 22:45:22 +09:00
Hide_D 06249f29cf game: 기병이 돌격 시 궁병 선제에 멈추도록 수정 2022-04-12 22:36:34 +09:00
Hide_D 242efc9ae7 fix: 궁병 수비시 선제로 인해 전투 로그가 두번 출력되는 버그 2022-04-12 22:27:48 +09:00
Hide_D c86572e6f3 game: 궁병에 회피 -5%p 2022-04-12 21:46:57 +09:00
Hide_D 03b458c1b2 game: 궁병에 '선제 사격' 추가
- 공격 시, 상대의 공격력을 1/2로 약화
- 수비 시, '선제 공격' 수행
   - 필살, 계략이 없는 일반 평타 공격
   - 공격자의 총 페이즈는 유지
2022-04-12 21:42:54 +09:00
Hide_D aa2e50366b feat: '선제 페이즈' 도입
- 일종의 '음수' 페이즈
   - 先 표기
   - 수비자 기준
- 내부의 currPhase가 변할 수 있도록 로직 변경
2022-04-12 21:40:49 +09:00
sarsandHide_D 657a47c9ad tournament (#214)
베팅창 QoL 개선

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/214
Co-authored-by: sars <sarsntony@gmail.com>
Co-committed-by: sars <sarsntony@gmail.com>
2022-04-10 17:46:28 +09:00
Hide_D 5d718bf4ea fix: 약탈발동에 저격특 효과 일부 코드가 남아 있던 버그 수정 2022-04-10 01:52:52 +09:00
Hide_D 082f847b1f game: 과실주(상성)를 대등한 병종에도 발동 2022-04-10 01:17:41 +09:00
Hide_D 54e4d74d0a fix: 장수 생성 페이지 너비 수정 2022-04-08 19:18:51 +09:00
Hide_D 1437d190e5 fix: 세력장수 이름 순에 NPC 정보 반영 2022-04-08 17:21:40 +09:00
Hide_D a95b26551c feat: 통합 세력 장수/암행부 페이지 (#213)
- ag-grid 기반
- 컬럼 사용자 정의 기능 제공
  - 컬럼 재정렬, 고정, 정렬 기능
  - 컬럼 상태 저장, 불러오기
  - 마지막 컬럼 재 사용
- 아이콘, 장수명 클릭 시 특수 기능 제공
  - 기본 세력 장수/암행부에서는 '감찰부'
- 추가 컬럼
  - 최근 전투
  - 전투 수
  - 승리 수
  - 살상률
- API/Nation/GeneralList 추가

Co-authored-by: hide_d <hided62@gmail.com>
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/213
2022-04-08 02:28:58 +09:00
Hide_D c96f6d9381 fix: 초성 오토마타에서 head가 제때 정리되지 않는 버그 2022-04-06 02:41:24 +09:00
Hide_D c7df50d899 fix: vue-tsc 에러 반영 2022-04-05 23:06:58 +09:00
sars 29619ada08 유산 소모에 (필요 포인트가 피보나치식으로 증가합니다) 메세지 추가 2022-04-04 09:51:37 -07:00
Hide_D 222c8a25a4 fix: 최근 실행 턴이 '선택 해제된 턴'을 따르지 않는 버그 수정 2022-04-04 21:40:54 +09:00
sars eac9b7c2e2 오타 수정 (@/SammoAPI에서 ./SammoAPI)로 2022-04-04 00:19:32 -07:00
Hide_D 31d6349d71 fix,refac: ETag 오기록 수정, Cache 설정을 WebUtil로 2022-04-04 01:44:35 +09:00
Hide_D b67f4daf3a refac: 장수 생성페이지 GetConst 활용 2022-04-03 23:14:19 +09:00
Hide_D 81b81d9036 feat: Global/GetConst API의 Store파트 2022-04-03 23:13:31 +09:00
Hide_D 2d06f368f8 refac: APICall에 타입 지정
- 비 undefined 타입에서 ?타입 호출 제거
- API 소속 type들을 defs/API/ 로 이동
- 모든 SammoAPI, SammoRootAPI 지정
2022-04-03 18:16:53 +09:00
Hide_D d0dc0f2bd1 fix: SammoAPICall에서 arg가 지정되어도 undefined가 가능한 버그 2022-04-03 17:15:36 +09:00
Hide_D e301c0fd3e refac: SammoAPI에 타입 지정 2022-04-03 02:17:14 +09:00
Hide_D 5879661267 refac, feat: API 호출 구조 재작성
- api.php에서 param path 강제
- api.php에서 GET param 허용
- SammoAPI 호출자를 axios에서 fetch 기반(ky)로 변경
- SammoAPI에서 단순 POST대신 REST에 따라 지정 가능하도록 재구성
- SammoAPI에서 NumVar, StrVar를 PathParam으로 변경하도록 변경
- API CallType들을 def/API로 분리 시작
  - 일부 API를 시험삼아 변경(login)
2022-04-02 23:31:05 +09:00
Hide_D ad1f070557 feat: 정적 변수를 반환하는 API 추가 Global/GetConst 2022-04-02 18:42:13 +09:00
Hide_D c20986b7b7 misc: BaseNation에서도 getInfo fallback 추가 2022-04-02 18:40:58 +09:00
Hide_D 153f425c99 refac: APIHelper 반환 값 정리 2022-04-02 18:39:47 +09:00
Hide_D 6eb202d4b2 misc: api cache max-age 단축
- 실제 캐시는 etag와 last-modified의 304 반환 활용
- http 2.0을 목표로하므로 큰 문제는 없을 것
2022-04-02 03:12:38 +09:00
Hide_D f7e46e16a3 fix: cache control에서 expires가 남는 문제 수정 2022-04-02 01:17:08 +09:00
Hide_D 36d7e22040 fix: api.php 설정이 전혀 동작하지 않던 문제 수정 2022-04-02 01:14:46 +09:00
Hide_D b24c4806f5 fix: APIHelper에서 tryCache가 잘못된 타입 지정인 버그 2022-04-01 23:27:04 +09:00
Hide_D 8ab79ad9f4 fix: 악질유저무쌍(비급) 시나리오 누락 2022-03-31 19:57:49 +09:00
Hide_D 4f4533e533 refac: linter 관련 설정 변경 및 적용, map_theme 변수 제거
- eslint에 prettier 조합
- prettierrc에 width 120, tabWidth 2
- gameStor->map_theme 제거
- map_theme, mapTheme를 GameConst::$mapName으로 대체
- eslint에서 vue/vue3-essential 대신 vue3-recommended 적용
  - vue/max-attributes-per-line 완화
  - vue/v-on-event-hyphenation 해제
  - vue/attribute-hyphenation 해제
- 일부 tsc import type warning 해결
- 일부 vue template type warning 해결
- 일부 vue SFC를 script setup으로 변경
  - TipTap
  - TopBackBar
  - BottomBackBar
  - BoardArticle
  - ProcessCity
2022-03-29 02:06:47 +09:00
Hide_D e569ffe8f4 build: eslint에서 vue/setup-compiler-macros 활성화
- 필요없어진 import 제거
2022-03-28 22:31:10 +09:00
Hide_D e09709651c fix: 지급률 계산식에서 부대장이 포함되는 버그 수정 2022-03-28 01:15:20 +09:00
Hide_D 39d7b6d55c fix: 1인국 n장 군주일때 발생하는 버그 수정
- 12월, 6월 지급률 계산 시
2022-03-28 01:11:05 +09:00
Hide_D 2b2a328062 game: 계략 성공률 한도를 50%로 제한 2022-03-27 16:55:47 +09:00
Hide_D 65e1495b44 fix: 베팅 대상에 들어가지 않은 국가가 성공 대상인 경우 버그
- purifyBettingKey에서 '해당 국가 없음' 에러를 내지 않도록 변경
2022-03-27 13:11:08 +09:00
Hide_D 3400f5843e game: 도기 판매시 국고와 개인 재산으로 반반씩 2022-03-27 03:54:37 +09:00
Hide_D e580691c1d fix: 백성동원 전략 사용시 국가 열전에 잘못된 양식으로 기록되는 버그 수정 2022-03-27 03:21:55 +09:00
Hide_D bb0e817943 game: 누락된 NPC 비중 수식 반영 2022-03-27 02:49:37 +09:00
Hide_D b7e4db6acd game: 랜임시 유저장 비중 보정
- NPC가 많은 국가가 기존보다 살짝 더 강해짐
- 여전히 유저 위주국가보다 불리
2022-03-27 00:50:03 +09:00
Hide_D 366fe5d613 refac: 시계부분을 분리하여 vue render 최적화 2022-03-27 00:06:40 +09:00
Hide_D 428f2706c3 feat: 최근 실행턴의 중복 관리를 개선 2022-03-26 23:44:01 +09:00
Hide_D 7f2b4596f7 fix: 사령부에서 최근 턴 저장 안되는 버그 수정 2022-03-26 23:30:20 +09:00
Hide_D ab9bdf3822 feat: 사령부의 턴 선택기에 고급 모드 적용 (#212)
- 사령부 턴 페이지를 vue3 setup 형태로 변경
- 턴 조작기 함수 중 공용 함수 분리
- 사령부 턴 조작기 코드 범위를 다시 조정
- 사령부 일반 모드, 고급 모드 이원화
- 사령부에서 다른 수뇌의 턴 '복사하기' 제공

Co-authored-by: Hide_D <hided62@gmail.com>
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/212
Co-authored-by: hide_d <hided62@gmail.com>
Co-committed-by: hide_d <hided62@gmail.com>
2022-03-26 23:11:58 +09:00
Hide_D 585667dfe8 fix: 토너먼트 참가시 한쪽 슬롯이 가득 차면 입장이 닫히는 버그 2022-03-26 17:01:59 +09:00
Hide_D 151e6ed1f3 fix: 세력일람 확장에서 NPC 색상이 고정되는 버그 수정 2022-03-26 02:36:39 +09:00
Hide_D 0685d1caac fix: APIPathGen에서 Var 모드 사용시 에러 2022-03-26 00:04:18 +09:00
Hide_D f50ba83d31 fix: APIPathGen 호출 시 중간 경로 캐싱시 버그 수정 2022-03-25 23:50:41 +09:00
Hide_D 24c043386d refac: SammoAPI Path 정의에 NumVar, StrVar 추가 2022-03-25 23:29:10 +09:00
Hide_D 9d868cb2f4 refac: SammoAPI에서 인자, 반환 타입을 사전 지정 가능 2022-03-25 22:48:34 +09:00
Hide_D be308fdb4a fix: 불가침제의를 원래 의도대로 6개월로 변경 2022-03-24 10:59:04 +09:00
Hide_D 73a5f5287b fix: 중원 정보 표기 에러 수정 시도 2022-03-24 10:37:25 +09:00
Hide_D acafb15215 feat: 여러턴 예약을 ReserveBulkdCommand로 대체 2022-03-24 00:34:05 +09:00
Hide_D 79b9e1b22a fix: 연감 staticValues 중복 2022-03-23 23:51:29 +09:00
Hide_D 7ebdef3116 fix: 연감 표기를 staticValues export에 따라 수정 2022-03-23 23:45:29 +09:00
Hide_D a3fbaa0038 fix: 에러 로그에 따라 수정
- 임관, 하야 등에서 탑승 부대 해제
- 외교 서신 회수시 warning
- DummyGeneral에서 능력치 참조 시.
2022-03-23 23:40:50 +09:00
Hide_D fea2163a01 fix: 세력도시 style 문법 오류 2022-03-23 23:18:00 +09:00
Hide_D d55443968f fix: 세력도시 style 문법 오류 2022-03-23 23:15:11 +09:00
Hide_D b08a2681a2 feat: 세력도시에서 수입 정보 표기, NPC 색 누락분 수정 2022-03-23 23:13:28 +09:00
Hide_D 48af7e5e76 fix: 커맨드 선택시 '간이 복사' 기능이 남아있던 버그 2022-03-23 22:07:59 +09:00
Hide_D 98f48441c9 game: 내정 1% 감소 후, 세율 반영하도록 변경 2022-03-23 20:26:07 +09:00
Hide_D 65f2836379 game: 악질유저무쌍! 시나리오 추가 2022-03-23 20:20:48 +09:00
Hide_D 3548d4e939 feat: 턴 선택기를 재 작성 (#211)
- select form에서 유사 dialog 버튼 방식으로 변경
  - 카테고리마다 페이지 이동
- 일반 모드 / 고급 모드 분리
- 일반 모드에서는 턴별 즉시 설정
- 고급 모드에서는 드래그를 포함한 각종 기능 제공
  - 최근 실행 턴
  - 잘라내기, 복사하기, 붙여넣기
  - 반복하기
  - 비우기
  - 지우고 당기기, 뒤로 밀기
  - 보관하기, 보관한 턴 사용하기

Co-authored-by: Hide_D <hided62@gmail.com>
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/211
Co-authored-by: hide_d <hided62@gmail.com>
Co-committed-by: hide_d <hided62@gmail.com>
2022-03-23 20:13:27 +09:00
Hide_D eb03f34a7e fix: 이미지 안올라가는 버그 수정 2022-03-23 01:01:47 +09:00
Hide_D 40b1a9fbdf build: bootstrap-vue-3
- tiptap/CustomImage 정의 문제 수정
- useToast() 관련 문제 수정
2022-03-20 18:37:38 +09:00
Hide_D 76a31acadc build: tsconfig 변경
- 반영된 룰에 맞게 import type 적용
2022-03-20 12:45:05 +09:00
Hide_D 0f71d786f7 fix: 빙의에서 장수 목록 보기를 사용할 수 없음 2022-03-20 12:14:20 +09:00
sars fec2508091 토너먼트 하이라이트와 토너먼트 액티브를 따로 변수로 저장 2022-03-16 23:10:54 -07:00
sars 4f087754e2 참가중일때만 토너먼트 액티브 설정 2022-03-16 20:24:12 -07:00
sars 520dbb23f2 Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2022-03-16 12:12:46 -07:00
sars e8f2538510 토너먼트와 베팅장 하이라이트하기. (모바일에서 dropdown-item에서는 아직 적용 못함) 2022-03-16 12:09:29 -07:00
Hide_D fa6b271994 refac: schema.sql COLLATE, json_valid 지정 2022-03-16 23:44:12 +09:00
Hide_D c4aa6b4ffc game: 조기 은퇴 커맨드 추가 2022-03-16 01:30:47 +09:00
Hide_D 4bb1bac5d1 game: 유저장 자동 금쌀매매 기준 추가 변경 2022-03-16 00:38:18 +09:00
Hide_D 79815f99fc game: 유저장 자동 금쌀매매 기준 변경
- 3번 전멸하는 동안 필요한 금쌀을 모두 가지고 있을 경우 군량매매하지 않음
2022-03-16 00:02:38 +09:00
Hide_D 1342fb5cc1 game: 천통국 결정 시 자동으로 임관 금지 설정 2022-03-15 23:43:43 +09:00
Hide_D eae488b44f feat: BlockScoutAction Action 추가
- 모든 국가의 임관 설정을 임의 설정하는 이벤트 액션
2022-03-15 23:20:28 +09:00
sars 72200683fe serverNameWithCount를 serverName과 serverCnt로 나눔 2022-03-14 19:39:35 -07:00
sars c506d608c2 Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2022-03-14 14:07:01 -07:00
sars 69348680d5 서버 이름과 횟수를 printStaticValue에 추가 2022-03-14 14:06:08 -07:00
Hide_D f6b359955d game,fix: 백이병 vs 정란, 벽력거 공격 상성 관련 문제 수정 2022-03-14 22:27:13 +09:00
Hide_D 0d4a68daea misc: gitignore update 2022-03-14 22:13:06 +09:00
sars dfff94f319 동결상태를 isLocked로 printStaticValue에 추가 2022-03-14 03:42:04 -07:00
sars 8cff55b5ed lastExecuted를 printStaticValues에 추가 2022-03-14 03:07:16 -07:00
Hide_D d61143c2ad misc: README 변경 2022-03-13 21:40:53 +09:00
Hide_D 1afe999beb Merge pull request 'feat: php vendor를 동적으로 구성하도록 변경' (#209) from no_php_vendor_code into devel
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/209
2022-03-13 21:15:42 +09:00
Hide_D 0dd3def0d5 fix: composer 준비 전에도 j_install_status가 응답해야함 2022-03-13 21:03:39 +09:00
Hide_D 0a1d81be76 fix: Web UI로 초기 install이 불가능한 버그 수정 2022-03-13 20:16:54 +09:00
Hide_D 91ea0d1c2a build: 빌드 환경 재 설정
- lock에 따라 npm ci로 변경
- webpack build를 서버 내에서 하므로 dev dependency가 거의 없음
- webpack build에서 gateway build를 별도로 작성
2022-03-13 19:47:24 +09:00
Hide_D 5fe9136aa1 fix: 초기 index.php에서 vendor/autoload.php 검사 2022-03-13 19:06:31 +09:00
Hide_D 3ef91d3617 feat: install에서 composer update도 수행. update 기준 변경
- lock file을 git에 추가하였으므로, 이에 따름
2022-03-13 18:56:29 +09:00
Hide_D 0aa73c2f62 dep: vendor directory 제거 2022-03-13 18:33:09 +09:00
Hide_D d8ad26f83c dep: composer update 2022-03-13 16:55:04 +09:00
Hide_D 85a9f127bd fix: oauth_kakao에서 누락된 userID 반영 2022-03-13 13:46:13 +09:00
Hide_D edd5248d50 fix: COMPRESSED 타입 table 제거 2022-03-13 13:42:40 +09:00
Hide_D 892d13212d dep: npm package update. package-lock.json 해제 2022-03-13 01:59:55 +09:00
Hide_D 0ab485f122 feat: 해시 기반 간이 DRBG, 그에 기반한 RandUtil (#208)
기존의 Util 내의 함수는 mt_rand에 기반하고 있어서 일반적으론 충분하지만,
게임 내부에서 랜덤 값을 정교하게 제어하고 싶은 경우에는 적절하지 않았음.

따라서 직접 seed를 제어할 수 있는 난수생성기를 추가.
SHA512(seed || blockIdx) 의 형태로 동작하는 DRBG이며, FIPS 표준을 따르는 RNG는 아니지만 암호학적으로 안전한 형태로 구현함.

PHP, TS 두가지 형태로 구현.

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/208
Co-authored-by: hide_d <hided62@gmail.com>
Co-committed-by: hide_d <hided62@gmail.com>
2022-03-12 23:53:16 +09:00
Hide_D c220b3d511 game: 정란 상성 공격력 상향, 차병 비용 절감 2022-03-12 20:11:36 +09:00
Hide_D 57bb22497e game: 이세계무쌍- 유저무쌍 멀티 유니버스 수정 2022-03-10 23:12:47 +09:00
Hide_D 1ae95ba4bc feat: NPC 추방,몰수, 고유메시지 빈도를 GameConst에서 조절 2022-03-10 23:11:56 +09:00
Hide_D 90b3684cdb game: 이세계무쌍 비급 시나리오 추가 2022-03-08 22:07:19 +09:00
Hide_D 15d6c427eb game: 이세계무쌍 시나리오 등록 2022-03-08 21:58:23 +09:00
Hide_D c68a428bf5 feat: 유닛테스트 준비 2022-03-03 00:16:01 +09:00
Hide_D a289b192e4 dep: typescript test 기반 추가 2022-03-02 23:31:32 +09:00
Hide_D 356f3af919 dep: phpunit 추가 2022-03-02 23:29:09 +09:00
Hide_D a660ec4cca fix: 커맨드 실행 조건 강제 탈출 조건을 잘못 작성하는 버그 수정 2022-03-01 12:29:21 +09:00
sars 4c9ddcb272 $general->getVar('nation')로 수정 2022-02-25 20:19:56 -08:00
sars 5131a36e20 general -> $general, 오타수정 2022-02-25 20:16:48 -08:00
sars 87c055563d 급하게 도기 코드 수정, 냐섭에서 테스트할 예정 2022-02-25 20:09:03 -08:00
sars 124c27cf17 동결풀기위해 도기템을 임시로 일단 주석처리함 2022-02-25 19:41:10 -08:00
Hide_D 4f0dbf0f92 feat: api.php 호출에서 path를 경로로 지정하는 방식 추가 2022-02-25 01:54:22 +09:00
Hide_D 6e24ca230d fix: 연감 static var 출력 버그 수정 2022-02-25 01:24:02 +09:00
Hide_D ac6e1d2525 fix: 1개 선택 베팅 보상 예측값이 잘못 설정된 버그 2022-02-24 00:22:27 +09:00
Hide_D 610b74d3a5 game: 표준 공백지 시나리오에 천통 베팅 추가 2022-02-24 00:15:36 +09:00
Hide_D 7f295aaacf fix: 탑 바 메뉴에서 세력도 제거. 세력도 페이지 제거 2022-02-23 23:55:18 +09:00
Hide_D a47669ff75 feat: 연감에 기존 세력도 기능 통합 2022-02-23 23:46:40 +09:00
Hide_D 9f84eb8d4d game,feat: 소비형 아이템 효율 상승, 환약 3회용으로 변경 2022-02-23 01:41:24 +09:00
Hide_D 5f36143b44 game: 숙련도로 얻는 유산 포인트 감소 2022-02-23 00:21:02 +09:00
Hide_D 2d491dd393 fix: 2회 이상 연속 전투에 성벽 전투가 포함된 경우 대인 사살이 계산되지 않는 버그 2022-02-22 23:55:13 +09:00
Hide_D 63845afdc3 fix: 재난 시 전체 이벤트 처리를 위해 column 추가 2022-02-22 15:39:43 +09:00
Hide_D 3cfcfff786 fix: 방어 대상에 crewtype 포함 2022-02-22 14:41:37 +09:00
Hide_D 9f801df5dc game: 평시 유니크 획득 확률 변경 2022-02-22 00:43:22 +09:00
Hide_D 21b8c6ea8f game: 작위 보상에서 아이템이 없는 사람이 받을 확률 대폭 증가 2022-02-22 00:28:35 +09:00
Hide_D 0807f9912c game: 반계도구 제거, 도구 밸런스 조정 2022-02-22 00:14:20 +09:00
Hide_D 90a71ba75d fix: 아이템 판매시 에러 방지 2022-02-20 15:31:52 +09:00
Hide_D 2e26244992 fix: 전투력보정에 unit이 제공되지 않음 2022-02-20 15:13:39 +09:00
Hide_D 8f1e713451 fix: 이벤트로 모든 장수의 지출이 0인 경우 대비 2022-02-20 14:57:56 +09:00
Hide_D b7b5c7b0da game: 아이템을 실제로 사용할 수 있도록 등록 2022-02-20 14:51:04 +09:00
Hide_D cb42813597 fix: 오타 수정 2022-02-20 05:11:26 +09:00
Hide_D 91c46f465b feat,game: 장비매매시 반응하는 트리거 추가, 판매시 국고에 추가되는 유니크 추가 2022-02-20 04:34:10 +09:00
Hide_D 435044dddd feat: 임의 커맨드용 트리거 추가 2022-02-20 04:30:05 +09:00
Hide_D cccf9968e7 game: 의술 유니크 추가 2022-02-20 04:10:34 +09:00
Hide_D f1e4185193 game: 비전투 커맨드 효율 유니크 추가 2022-02-20 04:02:35 +09:00
Hide_D dc538af7ba game,feat: 추가 숙련 trigger추가, 숙련 유니크 추가 2022-02-20 04:01:55 +09:00
Hide_D 574ca07afe game,feat: 조달 효율 변경 trigger 추가, 조달 유니크 추가 2022-02-20 04:01:03 +09:00
Hide_D f18b2ed1a5 fix: 능력치 유니크 오타 수정 2022-02-20 03:38:50 +09:00
Hide_D bc568e2083 game: 전투 특기 반영 유니크 도구 추가 2022-02-20 03:37:15 +09:00
Hide_D bffdf9d190 game: 1회저지, 회피저지 유니크 추가 2022-02-20 03:17:35 +09:00
Hide_D e7af4563a2 feat,game: 반계불가 처리 추가, 반계불가 유니크 추가 2022-02-20 03:16:46 +09:00
Hide_D 5fc5adb14d feat,game: 전투 중 약탈 추가, 약탈 유니크 추가 2022-02-20 03:13:03 +09:00
Hide_D f3ccf5e633 game: 경과 시간에 따라 변하는 유니크 추가 2022-02-20 03:12:17 +09:00
Hide_D 46cacc4a7d game,feat: 계략 커맨드 방어 유니크
- 계략 방어 확률에 보정 trigger 추가
2022-02-20 03:11:02 +09:00
Hide_D ac8edcee32 game: 회피 유니크 조절 2022-02-20 03:09:59 +09:00
Hide_D 919c44c727 game,feat: 전투력보정 관련 유니크 도구 추가
- 직접 전투력보정을 위한 WarUnitTrigger 추가
2022-02-20 03:08:24 +09:00
Hide_D 95921ae727 game: 사기, 훈련 유니크 수치 변경 2022-02-20 03:04:45 +09:00
Hide_D 134f043e9c refac: 아이템에 미사용 $id 값 제거 2022-02-19 23:54:03 +09:00
Hide_D a7a14a66a6 game: 벽력거를 진짜 무상성 병종으로 2022-02-19 17:55:29 +09:00
Hide_D 148d92164a refac: 장수 생성시 임관권유문 문구 변경
- coreui/vue 의존성 제거
2022-02-18 21:15:06 +09:00
Hide_D 5ea1b0bce4 refac: toast 출력을 bootstrap-vue-3 내부 toast로 변경
- component로 src 내부 ts/vue 사용 시도 중
2022-02-18 20:54:26 +09:00
Hide_D 65aefadcdc dep: package updates 2022-02-18 13:39:46 +09:00
Hide_D 1bc324fb9f fix: turnExecutionHelper env 관련 수정 2022-02-18 11:27:29 +09:00
Hide_D 28953ae1d9 fix: 토너먼트 참가 시점에서 생존여부 확인 2022-02-18 10:55:25 +09:00
Hide_D 3760e244a9 scenario: 천지비급에 '견고' 추가 2022-02-16 22:55:47 +09:00
Hide_D e86d755b69 scenario: 천지비급에서는 183년 이전에 항상 상인 2022-02-16 22:52:01 +09:00
Hide_D 6f560a1b34 버그 수정 2022-02-14 00:26:42 +09:00
Hide_D 6fe573ef7b fix: 토너먼트 실행 주기에서 초기화시 '수동'뜨는 문제 2022-02-08 20:39:49 +09:00
Hide_D 2a7baf020f misc: 연도 갱신 2022-02-06 12:08:58 +09:00
Hide_D 2e1815783a fix: 커맨드 세부 선택시 스탯 표기 오류 수정
- 통/무/지 순이어야함
2022-02-06 12:06:14 +09:00
Hide_DandGitea bab86c9f0b feat: 변경된 베팅 방식에 따라 결과 표기 2022-02-05 07:43:28 +00:00
Hide_DandGitea 2716e9af39 refac: 베팅 코드를 모듈로 2022-02-05 07:43:28 +00:00
Hide_DandGitea 9a303c4510 fix: n차 혼합 베팅 보상 수령이 하나만 되는 버그 수정 2022-02-05 07:43:28 +00:00
Hide_DandGitea e547971a6f feat: 베팅시 유산포인트 로그에 추가 2022-02-05 07:43:28 +00:00
Hide_DandGitea e9108ead86 feat: 베팅 보상 등록 2022-02-05 07:43:28 +00:00
Hide_DandGitea 6bbcb25138 feat(WIP): 베팅 보상 누락 수정 2022-02-05 07:43:28 +00:00
Hide_DandGitea 98462ca34d feat(WIP): 보상을 위한 Betting 모듈 추가 2022-02-05 07:43:28 +00:00
Hide_DandGitea 7939dd0b44 feat: 메인 페이지에 토너먼트 개최기간 표기 2022-02-05 07:43:27 +00:00
Hide_DandGitea 3d966ec076 fix: 베팅시 추가 포인트 부여 불가 2022-02-05 07:43:27 +00:00
Hide_DandGitea 6afedb35df Revert "fix: 베팅시 추가 포인트 부여 불가"
This reverts commit 6fb4a1b274.
2022-02-05 07:43:27 +00:00
Hide_DandGitea cdac63e05a fix: 베팅시 추가 포인트 부여 불가 2022-02-05 07:43:27 +00:00
Hide_DandGitea 8040cc28c4 fix: 베팅 순서 수정 2022-02-05 07:43:27 +00:00
Hide_DandGitea 264db40bdc fix: 베팅 관련 사소한 버그 수정
- 베팅이 없을 경우
- 베팅 동시 신청
2022-02-05 07:43:27 +00:00
Hide_DandGitea 2da1957c28 feat: 국가 베팅 ui 2022-02-05 07:43:27 +00:00
Hide_DandGitea 2297fa9c13 fix: NPCControl volar error 2022-02-05 07:43:27 +00:00
Hide_DandGitea 8175e76a77 build: warning 기준 변경
- 5MB, 3MB.......
2022-02-05 07:43:27 +00:00
Hide_DandGitea 2709dde8fa fix: template 2022-02-05 07:43:27 +00:00
Hide_DandGitea 7c518efba8 fix: volar error 수정
- getNPCColor 반환형
2022-02-05 07:43:27 +00:00
Hide_DandGitea b5fa2aef91 game: npc 색상 분리 2022-02-05 07:43:27 +00:00
Hide_DandGitea d2f6c34e85 fix: 베팅 시 key 정렬을 숫자 정렬로 2022-02-05 07:43:27 +00:00
Hide_DandGitea cd1ccfadaf fix: 세력일람 분석에서 자동수행턴을 반영하지 않는 버그 수정 2022-02-05 07:43:27 +00:00
Hide_DandGitea 8ff6bff252 game: 장수 생성시 종능이 부족하면 경고 2022-02-05 07:43:27 +00:00
Hide_DandGitea 52f6cb2f30 fix: 피장파장 시, 턴이 60턴이 늘어나는 것이 아니라 60턴이 되는 버그 수정 2022-02-05 07:43:27 +00:00
Hide_DandGitea e7af718a0f feat(WIP): 국가 베팅 '기능만' 구현 2022-02-05 07:43:27 +00:00
Hide_DandGitea d211c92bf8 fix: type react가 volar에서 문제를 일으킴 2022-02-05 07:43:27 +00:00
Hide_DandGitea 4acc988cfe feat(WIP): 베팅 개시 타입 변경
-candidate를 미리 추가.
-이를 통해 betting을 중립적으로 운용 가능
2022-02-05 07:43:27 +00:00
Hide_DandGitea 270f236f95 feat(WIP): OpenNationBetting에 보너스 상금 추가 2022-02-05 07:43:27 +00:00
Hide_DandGitea 2da12bb71f fix: 이벤트 조건 오류 수정 2022-02-05 07:43:27 +00:00
Hide_DandGitea b479add03d misc: OpenNationBetting TODO 추가 2022-02-05 07:43:27 +00:00
Hide_DandGitea ca9db6dc18 Feat(WIP): OpenNationBetting Action 추가
- 시나리오 event에 추가
2022-02-05 07:43:27 +00:00
Hide_DandGitea 12c7c7b4ed feat(WIP): 이벤트 시나리오에서 불가능한 커맨드 지정 2022-02-05 07:43:27 +00:00
Hide_DandGitea e12c0e51c8 fix: 시나리오 모드에서 시작시점과 봉급월이 겹치는 경우 멈추는 문제 수정 2022-02-05 07:43:27 +00:00
Hide_DandGitea 6683c70195 fix: N장만 건국한 경우에 CreateManyNPC가 동작하지 않는 버그 수정 2022-02-05 07:43:27 +00:00
Hide_DandGitea aef1cbd201 fix: 봉급 계산에서 부대장 처리를 하지 않은 문제 수정
- 전체 지출 계산에만 실수 발생
2022-02-05 07:43:27 +00:00
Hide_DandGitea 06786aff28 feat(WIP): 이벤트 시나리오 준비 2022-02-05 07:43:27 +00:00
Hide_DandGitea 55439c268f feat: Event/Condition/RemainNation 추가 2022-02-05 07:43:27 +00:00
Hide_DandGitea 3e4cf764c8 feat: 시나리오 event 포맷에서 target, priority 추가 2022-02-05 07:43:27 +00:00
Hide_DandGitea 4e359f5eb9 feat: 도시 점령, 국가 멸망 시 트리거 추가 2022-02-05 07:43:27 +00:00
Hide_DandGitea 2ff3746df2 feat: event 테이블 준비 2022-02-05 07:43:27 +00:00
Hide_DandGitea 62982d7ffb feat(WIP): 베팅 상세 정보 반환 2022-02-05 07:43:27 +00:00
Hide_DandGitea ec49cdb6ad feat: Global/GetNationList 추가
- 세력일람의 데이터와 원칙적으로 동일
2022-02-05 07:43:27 +00:00
Hide_DandGitea 4b64827f20 feat(WIP): 베팅 관련 작업중 2022-02-05 07:43:27 +00:00
Hide_DandGitea 944c4cb564 dep: DTO 2022-02-05 07:43:27 +00:00
Hide_DandGitea db19655b60 feat: ng_betting 테이블 추가 2022-02-05 07:43:27 +00:00
Hide_D 1975f11338 fix: 이전 로그 키 정렬 기준이 int가 아니라 string인 버그 수정 2022-02-04 12:55:37 +09:00
Hide_D 59515d5276 game: 이민족 발동 관련 변경
- 이민족 멸망 후 타국가 임관
- 이민족 발동 시 명성을 평균치로
2022-01-21 01:00:31 +09:00
Hide_D fea9529bc8 fix: 내무부, 기밀 제한이 잘못된 버그 수정 2022-01-07 19:40:35 +09:00
Hide_D 1f6259c157 game: 기병 공성 능력 약화, 수비시 공방 각각 5% 손해 2022-01-05 01:00:13 +09:00
Hide_D 8908e12c59 game: 유산으로 입찰된 유니크는 랜덤 유니크로 얻을 수 없음 2022-01-04 23:53:57 +09:00
Hide_D a7d6bc2c5c fix: 자동 사령턴 미 활성화 시 내정보&설정 에러 2022-01-04 06:32:45 +09:00
Hide_D 97fd807c2c fix: 단궁, 맥궁 증가 사기 표기량 수정 2022-01-03 22:45:27 +09:00
Hide_D b31f7d64ec game: 이중 격노가 발동하지 않도록 수정 2022-01-03 22:38:42 +09:00
Hide_D bdd574161e fix: 마지막 국가는 임관 불가능한 것처럼 나오는 버그 수정 2022-01-02 23:01:46 +09:00
Hide_D e23e36cbfa fix: 임관 제어 코드에서 () 누락 2022-01-02 22:50:42 +09:00
Hide_D fb796e21e4 fix: starts_with에 사소한 오류가 있어보임
- 이유는 잘 모르겠지만 starts_with($this->destNation['name'], 'ⓤ')
2022-01-02 22:46:32 +09:00
Hide_D dd46c02f09 feat: 게시판 500px 모드 2022-01-02 00:58:34 +09:00
Hide_D d1835c71b7 game: U국의 유저장간 거리를 4->3로 변경 2022-01-01 23:30:33 +09:00
Hide_D 55332864ad game: 토너먼트 자동 채우기 난이도 수정 2022-01-01 01:22:23 +09:00
Hide_D 96a8ef3bcc fix: 전금 증가 횟수 누락 2021-12-31 23:24:15 +09:00
Hide_D 79cfbfe83b fix: 전쟁 금지 설정 누락 부분 수정 2021-12-31 23:22:20 +09:00
Hide_D e7fa95ce8f fix: front에서 둔전 수입 계산 수정 2021-12-31 23:07:42 +09:00
Hide_D a819dde71c fix: 세수 표기를 잘못 반영하는 버그 수정 2021-12-31 23:05:22 +09:00
Hide_D 281cfd366b build: d_setting json ignore 2021-12-31 17:58:36 +09:00
Hide_D f1ba7e76f3 fix-build: install.php 초기 경로 관련 문제 수정 2021-12-31 17:55:29 +09:00
Hide_D 2da72d9b1a build: postcss 설정
- discard-dedupe
- autoprefixer
2021-12-31 17:33:15 +09:00
Hide_D 4cdc18fe7e misc: 사소하게 수정 2021-12-31 04:41:08 +09:00
Hide_D 4400116bdd feat: 내무부 변경 2021-12-31 04:12:37 +09:00
Hide_D 086d6d1ab5 misc: toast 내부 정리 2021-12-31 02:25:43 +09:00
Hide_D 02e86fd2e9 feat: toast내부 div 객체가 무한히 쌓이지 않도록 2021-12-31 02:22:42 +09:00
Hide_D 7310aa6971 feat(WIP): 내무부 국방/임관권유문 에디터 완료. 2021-12-30 22:50:33 +09:00
Hide_D 4927a26c92 misc: makeAPIPath 흔적 2021-12-29 05:50:21 +09:00
Hide_D ee6bec2e0d feat: APIPathGen 추상화 2021-12-29 05:46:35 +09:00
Hide_D def230bf30 feat: ts APICall을 강제화.
- 오버 엔지니어링의 정석
2021-12-29 03:55:40 +09:00
Hide_D 0a4d568b06 feat(WIP): 내무부 2021-12-28 04:29:13 +09:00
Hide_D 69f8e1f1bd feat: APIPathGen 도우미 2021-12-28 04:28:26 +09:00
Hide_D 6f2cb4e05e misc: 미사용 파일 제거 2021-12-27 21:54:23 +09:00
Hide_D db1fbb700c feat: 턴 선택기에서 '턴' 부분 선택 시 커맨드로 선택 2021-12-26 23:57:20 +09:00
Hide_D 842a37eb7b fix: 턴 선택기 홀짝 색 선택 오류 수정 2021-12-26 23:43:01 +09:00
Hide_D 76ff38ed10 feat: 사령부 턴 선택기 추가, 턴 해제 옵션 추가 2021-12-26 23:37:53 +09:00
Hide_D db6b2be101 feat: 턴 선택기에서 '드래그' 선택 지원 2021-12-26 23:22:43 +09:00
Hide_D a998500839 feat: DragSelect 추가
- Vue2 버전을 Vue3로 이식
2021-12-26 22:32:04 +09:00
Hide_D dd5e686d03 game: 유니크 명마, 명검, 서적 갯수 2배
- 말 유니크로 백상, 오환마, 흉노마, 의남백마, 옥추마, 화종마, 옥란백용구 추가
  - 백상, 옥란백용구는 특수효과 부여
2021-12-26 20:44:32 +09:00
Hide_D c9f28e27d2 feat: 소모 군량 보정을 위한 trigger 추가 2021-12-26 20:06:39 +09:00
Hide_D 1bbeb4f50d fix: 급습에서 대상국에 메시지가 뜨지 않음 2021-12-26 18:46:50 +09:00
Hide_D 410f6b261e fix: processing $destNation 구분 버그 2021-12-26 04:19:26 +09:00
4394 changed files with 50679 additions and 572640 deletions
+17 -5
View File
@@ -3,20 +3,23 @@ module.exports = {
parser: "vue-eslint-parser",
"env": {
"browser": true,
"es2021": true
"es2021": true,
'vue/setup-compiler-macros': true
},
ignorePatterns: ['*.test.ts', '.eslintrc.cjs', 'webpack.config.cjs', '*.js'],
ignorePatterns: ['*.test.ts', '.eslintrc.cjs', 'postcss.config.cjs', 'webpack.config.cjs', '*.js'],
overrides: [{
files: ['*.ts', '*.tsx', "*.vue"],
}],
plugins: [
"@typescript-eslint"
"@typescript-eslint",
"prettier"
],
extends: [
"eslint:recommended",
"plugin:vue/vue3-essential",
"plugin:@typescript-eslint/recommended"
"plugin:vue/vue3-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
],
parserOptions: {
"sourceType": "module",
@@ -27,6 +30,15 @@ module.exports = {
},
rules: {
'@typescript-eslint/no-floating-promises': 'error',
'vue/script-setup-uses-vars': 'error',
'vue/max-attributes-per-line': [
'warn',
{
singleline: 4, //prettier와 싸우지 말자
},
],
'vue/v-on-event-hyphenation': 'off', //vue3에선 필요없다고 생각
'vue/attribute-hyphenation': 'off', //vue3에선 필요없다고 생각
},
settings: {
'import/resolver': {
+7 -9
View File
@@ -5,8 +5,6 @@
!.vscode/extensions.json
/node_modules
package-lock.json
# 체섭 ignore
*.log
@@ -19,10 +17,7 @@ sess_*
*/logs/*/*.txt
*/logs/preserved
err.txt
che/.htaccess
kwe/.htaccess
pwe/.htaccess
twe/.htaccess
hwe/.htaccess
d_shared
@@ -43,10 +38,11 @@ d_pic/uploaded_image
d_setting/*.php
*/d_setting/*.php
*/d_setting/*.json
*/d_setting/templates/*.php
!*.orig.php
*/data/file_cache
**/data/file_cache
**/old/*
test.*
@@ -58,11 +54,13 @@ test.*
/pya
/twe
/hwe/data
/vendor
phpinfo.php
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
*.sqlite3
ingame/js/*
ingame/css/*
gateway/js/*
gateway/css/*
gateway/css/*
+12
View File
@@ -0,0 +1,12 @@
{
"extension": ["ts"],
"spec": "hwe/test-ts/**/*.test.ts",
"require": [
"ts-node/register",
"tsconfig-paths/register"
],
"node-option": [
"experimental-specifier-resolution=node",
"loader=ts-node/esm"
]
}
+3 -16
View File
@@ -15,7 +15,8 @@ return [
// Note that the **only** effect of choosing `'5.6'` is to infer
// that functions removed in php 7.0 exist.
// (See `backward_compatibility_checks` for additional options)
"target_php_version" => '8.0',
"target_php_version" => '8.1',
"minimum_target_php_version" => '8.1',
'backward_compatibility_checks ' => true,
'minimum_severity' => \Phan\Issue::SEVERITY_NORMAL,
@@ -39,11 +40,9 @@ return [
'hwe/a_emperior.php',
'hwe/a_genList.php',
'hwe/a_hallOfFame.php',
'hwe/a_history.php',
'hwe/a_kingdomList.php',
'hwe/a_npcList.php',
'hwe/api.php',
'hwe/a_status.php',
'hwe/a_traffic.php',
'hwe/a_vote.php',
'hwe/battle_simulator.php',
@@ -52,8 +51,7 @@ return [
'hwe/b_betting.php',
'hwe/v_chiefCenter.php',
'hwe/b_currentCity.php',
'hwe/b_dipcenter.php',
'hwe/b_diplomacy.php',
'hwe/v_nationStratFinan.php',
'hwe/b_genList.php',
'hwe/b_myBossInfo.php',
'hwe/b_myCityInfo.php',
@@ -64,7 +62,6 @@ return [
'hwe/b_tournament.php',
'hwe/b_troop.php',
'hwe/c_auction.php',
'hwe/c_dipcenter.php',
'hwe/c_tournament.php',
'hwe/c_vote.php',
'hwe/func_auction.php',
@@ -87,11 +84,9 @@ return [
'hwe/j_adjust_icon.php',
'hwe/j_autoreset.php',
'hwe/j_basic_info.php',
'hwe/j_betting.php',
'hwe/j_board_article_add.php',
'hwe/j_board_comment_add.php',
'hwe/j_board_get_articles.php',
'hwe/j_chief_turn.php',
'hwe/j_die_immediately.php',
'hwe/j_diplomacy_destroy_letter.php',
'hwe/j_diplomacy_get_letter.php',
@@ -102,17 +97,12 @@ return [
'hwe/j_general_log_old.php',
'hwe/j_general_set_permission.php',
'hwe/j_get_basic_general_list.php',
'hwe/j_getChiefTurn.php',
'hwe/j_get_city_list.php',
'hwe/j_get_general_list.php',
'hwe/j_get_nation_general_list.php',
'hwe/j_get_select_npc_token.php',
'hwe/j_get_select_pool.php',
'hwe/j_image_upload.php',
'hwe/j_install_db.php',
'hwe/j_install.php',
'hwe/j_load_scenarios.php',
'hwe/j_map_history.php',
'hwe/j_map.php',
'hwe/j_map_recent.php',
'hwe/j_msg_contact_list.php',
@@ -126,8 +116,6 @@ return [
'hwe/j_select_npc.php',
'hwe/j_select_picked_general.php',
'hwe/j_server_basic_info.php',
'hwe/j_set_chief_command.php',
'hwe/j_set_general_command.php',
'hwe/j_set_my_setting.php',
'hwe/j_set_npc_control.php',
'hwe/j_simulate_battle.php',
@@ -137,7 +125,6 @@ return [
'hwe/lib.php',
'hwe/process_war.php',
'hwe/proc.php',
'hwe/readme.php',
'hwe/recent_map.php',
'hwe/select_general_from_pool.php',
'hwe/select_npc.php',
+5
View File
@@ -0,0 +1,5 @@
{
"tabWidth": 2,
"useTabs": false,
"printWidth": 120
}
+2 -1
View File
@@ -13,7 +13,7 @@
"/nya":true,
"/pya":true,
"/twe":true,
},
"search.exclude": {
"e_lib/*":true,
@@ -29,4 +29,5 @@
"josa",
"sammo"
],
"editor.tabSize": 2
}
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License
Copyright (c) 2021 Hide_D, 62che
Copyright (c) 2022 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
+4 -4
View File
@@ -26,20 +26,20 @@ Docker를 이용한 설치도 제공하고 있습니다.
## Docker를 이용한 설치
https://storage.hided.net/gogs/devsam/docker 를 참고해 주세요.
https://storage.hided.net/gitea/devsam/docker 를 참고해 주세요.
## 수동 설치
본 게임은 <code>git</code>을 이용한 업그레이드 시스템을 구현하였으므로, <code>git</code>이 필요합니다.
또한 웹 서비스 데몬을 운영중인 사용자(일반적으로 <code>www-data</code>, <code>apache</code>)에게 디렉토리 권한이 주어져야합니다.
또한 웹 서비스 데몬을 운영중인 사용자(일반적으로 <code>www-data</code>)에게 디렉토리 권한이 주어져야합니다.
### 다운로드
웹 데몬 user가 <code>www-data</code>인 경우 다음과 같이 입력하여 최신 배포버전과 이미지 파일을 얻을 수 있습니다.
```
sudo -u www-data git clone https://storage.hided.net/gogs/devsam/core.git
sudo -u www-data git clone https://storage.hided.net/gogs/devsam/image.git
sudo -u www-data git clone https://storage.hided.net/gitea/devsam/core.git
sudo -u www-data git clone https://storage.hided.net/gitea/devsam/image.git
```
> 이미지는 hook/git_hook.php을 통해 동기화되며, 서버 설치 과정에 이미지 갱신 키를 지정하는 것으로 '훼' 서버 업데이트 시 동기화됩니다. 이미지 서버가 게임 서버와 별개여도 동작하나, php와 git을 지원해야합니다.
+5 -1
View File
@@ -8,5 +8,9 @@ require(__DIR__ . '/vendor/autoload.php');
if (!class_exists('\\sammo\\RootDB')) {
Json::dieWithReason('No DB');
}
$eParams = $_GET;
if(key_exists('path', $eParams)){
unset($eParams['path']);
}
APIHelper::launch(dirname(__FILE__));
APIHelper::launch(dirname(__FILE__), $_GET['path']??'', $eParams, true);
+9 -6
View File
@@ -25,30 +25,33 @@
"ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^1.5",
"phan/phan": "*",
"phan/phan": "^5.3",
"erusev/parsedown-extra": "^0.8.1",
"nette/caching": "^3.0",
"illuminate/database": "^8.61",
"illuminate/events": "^8.61"
"illuminate/events": "^8.61",
"spatie/data-transfer-object": "^3.7",
"php-ds/php-ds": "^1.4"
},
"autoload": {
"psr-4": {
"sammo\\": [
"d_setting",
"src/sammo"
],
"kakao\\": [
"d_setting",
"src/kakao"
]
},
"classmap": [
"d_setting/"
],
"exclude-from-classmap": [
"**/*.orig.php"
],
"files":[
"f_config/config.php"
]
},
"require-dev": {
"phpunit/phpunit": "^9.5"
}
}
Generated
+1928 -13
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": "94cfbcb22b9f475e421ad5009391006f",
"content-hash": "a32be16440b43a806002e52572e031db",
"packages": [
{
"name": "brandonwamboldt/utilphp",
@@ -1947,21 +1947,21 @@
},
{
"name": "phan/phan",
"version": "5.2.1",
"version": "5.3.2",
"source": {
"type": "git",
"url": "https://github.com/phan/phan.git",
"reference": "d724bbb8fc3ba89179868bb5220ecdf6a9c1636b"
"reference": "b7697eb811e912c038f709f8e1c4911c7ada3edc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phan/phan/zipball/d724bbb8fc3ba89179868bb5220ecdf6a9c1636b",
"reference": "d724bbb8fc3ba89179868bb5220ecdf6a9c1636b",
"url": "https://api.github.com/repos/phan/phan/zipball/b7697eb811e912c038f709f8e1c4911c7ada3edc",
"reference": "b7697eb811e912c038f709f8e1c4911c7ada3edc",
"shasum": ""
},
"require": {
"composer/semver": "^1.4|^2.0|^3.0",
"composer/xdebug-handler": "^1.3.2|^2.0.0",
"composer/xdebug-handler": "^2.0|^3.0",
"ext-filter": "*",
"ext-json": "*",
"ext-tokenizer": "*",
@@ -1969,8 +1969,8 @@
"microsoft/tolerant-php-parser": "^0.1.0",
"netresearch/jsonmapper": "^1.6.0|^2.0|^3.0|^4.0",
"php": "^7.2.0|^8.0.0",
"sabre/event": "^5.0.3",
"symfony/console": "^3.2|^4.0|^5.0",
"sabre/event": "^5.1.3",
"symfony/console": "^3.2|^4.0|^5.0|^6.0",
"symfony/polyfill-mbstring": "^1.11.0",
"symfony/polyfill-php80": "^1.20.0",
"tysonandre/var_representation_polyfill": "^0.0.2|^0.1.0"
@@ -1979,7 +1979,7 @@
"phpunit/phpunit": "^8.5.0"
},
"suggest": {
"ext-ast": "Needed for parsing ASTs (unless --use-fallback-parser is used). 1.0.1+ is needed, 1.0.14+ is recommended.",
"ext-ast": "Needed for parsing ASTs (unless --use-fallback-parser is used). 1.0.1+ is needed, 1.0.16+ is recommended.",
"ext-iconv": "Either iconv or mbstring is needed to ensure issue messages are valid utf-8",
"ext-igbinary": "Improves performance of polyfill when ext-ast is unavailable",
"ext-mbstring": "Either iconv or mbstring is needed to ensure issue messages are valid utf-8",
@@ -2020,9 +2020,64 @@
],
"support": {
"issues": "https://github.com/phan/phan/issues",
"source": "https://github.com/phan/phan/tree/5.2.1"
"source": "https://github.com/phan/phan/tree/5.3.2"
},
"time": "2021-09-15T00:08:40+00:00"
"time": "2022-02-01T00:17:36+00:00"
},
{
"name": "php-ds/php-ds",
"version": "v1.4.1",
"source": {
"type": "git",
"url": "https://github.com/php-ds/polyfill.git",
"reference": "43d2df301a9e2017f67b8c11d94a5222f9c00fd1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-ds/polyfill/zipball/43d2df301a9e2017f67b8c11d94a5222f9c00fd1",
"reference": "43d2df301a9e2017f67b8c11d94a5222f9c00fd1",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": ">=7.0"
},
"provide": {
"ext-ds": "1.3.0"
},
"require-dev": {
"php-ds/tests": "^1.3"
},
"suggest": {
"ext-ds": "to improve performance and reduce memory usage"
},
"type": "library",
"autoload": {
"psr-4": {
"Ds\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rudi Theunissen",
"email": "rudolf.theunissen@gmail.com"
}
],
"keywords": [
"data structures",
"ds",
"php",
"polyfill"
],
"support": {
"issues": "https://github.com/php-ds/polyfill/issues",
"source": "https://github.com/php-ds/polyfill/tree/v1.4.1"
},
"time": "2022-03-09T20:39:30+00:00"
},
{
"name": "php-extended/php-system",
@@ -2636,6 +2691,69 @@
},
"time": "2021-06-29T04:31:23+00:00"
},
{
"name": "spatie/data-transfer-object",
"version": "3.7.3",
"source": {
"type": "git",
"url": "https://github.com/spatie/data-transfer-object.git",
"reference": "341f72c77e0fce40ea2e0dcb212cb54dc27bbe72"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/data-transfer-object/zipball/341f72c77e0fce40ea2e0dcb212cb54dc27bbe72",
"reference": "341f72c77e0fce40ea2e0dcb212cb54dc27bbe72",
"shasum": ""
},
"require": {
"php": "^8.0"
},
"require-dev": {
"illuminate/collections": "^8.36",
"jetbrains/phpstorm-attributes": "^1.0",
"larapack/dd": "^1.1",
"phpunit/phpunit": "^9.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Spatie\\DataTransferObject\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Brent Roose",
"email": "brent@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"description": "Data transfer objects with batteries included",
"homepage": "https://github.com/spatie/data-transfer-object",
"keywords": [
"data-transfer-object",
"spatie"
],
"support": {
"issues": "https://github.com/spatie/data-transfer-object/issues",
"source": "https://github.com/spatie/data-transfer-object/tree/3.7.3"
},
"funding": [
{
"url": "https://spatie.be/open-source/support-us",
"type": "custom"
},
{
"url": "https://github.com/spatie",
"type": "github"
}
],
"time": "2021-12-30T20:31:10+00:00"
},
{
"name": "symfony/console",
"version": "v5.3.10",
@@ -4165,7 +4283,1804 @@
"time": "2019-08-07T17:19:21+00:00"
}
],
"packages-dev": [],
"packages-dev": [
{
"name": "doctrine/instantiator",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b",
"reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^8.0",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.13 || 1.0.0-alpha2",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.0"
},
"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%2Finstantiator",
"type": "tidelift"
}
],
"time": "2020-11-10T18:47:58+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.10.2",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220",
"reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"replace": {
"myclabs/deep-copy": "self.version"
},
"require-dev": {
"doctrine/collections": "^1.0",
"doctrine/common": "^2.6",
"phpunit/phpunit": "^7.1"
},
"type": "library",
"autoload": {
"files": [
"src/DeepCopy/deep_copy.php"
],
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.10.2"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
"time": "2020-11-13T09:40:50+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.13.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "210577fe3cf7badcc5814d99455df46564f3c077"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077",
"reference": "210577fe3cf7badcc5814d99455df46564f3c077",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2"
},
"time": "2021-11-30T19:35:32+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/2.0.3"
},
"time": "2021-07-20T11:28:43+00:00"
},
{
"name": "phar-io/version",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
},
{
"name": "Sebastian Heuer",
"email": "sebastian@phpeople.de",
"role": "Developer"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "Developer"
}
],
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/3.2.1"
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "phpspec/prophecy",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.2",
"php": "^7.2 || ~8.0, <8.2",
"phpdocumentor/reflection-docblock": "^5.2",
"sebastian/comparator": "^3.0 || ^4.0",
"sebastian/recursion-context": "^3.0 || ^4.0"
},
"require-dev": {
"phpspec/phpspec": "^6.0 || ^7.0",
"phpunit/phpunit": "^8.0 || ^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Prophecy\\": "src/Prophecy"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"description": "Highly opinionated mocking framework for PHP 5.3+",
"homepage": "https://github.com/phpspec/prophecy",
"keywords": [
"Double",
"Dummy",
"fake",
"mock",
"spy",
"stub"
],
"support": {
"issues": "https://github.com/phpspec/prophecy/issues",
"source": "https://github.com/phpspec/prophecy/tree/v1.15.0"
},
"time": "2021-12-08T12:19:24+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.14",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "9f4d60b6afe5546421462b76cd4e633ebc364ab4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f4d60b6afe5546421462b76cd4e633ebc364ab4",
"reference": "9f4d60b6afe5546421462b76cd4e633ebc364ab4",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.13.0",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
"sebastian/code-unit-reverse-lookup": "^2.0.2",
"sebastian/complexity": "^2.0",
"sebastian/environment": "^5.1.2",
"sebastian/lines-of-code": "^1.0.3",
"sebastian/version": "^3.0.1",
"theseer/tokenizer": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcov": "*",
"ext-xdebug": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.2-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.14"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-28T12:38:02+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"ext-pcntl": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcntl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Invoke callables with a timeout",
"homepage": "https://github.com/sebastianbergmann/php-invoker/",
"keywords": [
"process"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
"source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:58:55+00:00"
},
{
"name": "phpunit/php-text-template",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T05:33:50+00:00"
},
{
"name": "phpunit/php-timer",
"version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
"source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:16:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "9.5.16",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "5ff8c545a50226c569310a35f4fa89d79f1ddfdc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5ff8c545a50226c569310a35f4fa89d79f1ddfdc",
"reference": "5ff8c545a50226c569310a35f4fa89d79f1ddfdc",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.3.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.10.1",
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
"phpspec/prophecy": "^1.12.1",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.5",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.3",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^2.3.4",
"sebastian/version": "^3.0.2"
},
"require-dev": {
"ext-pdo": "*",
"phpspec/prophecy-phpunit": "^2.0.1"
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
}
},
"autoload": {
"files": [
"src/Framework/Assert/Functions.php"
],
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.16"
},
"funding": [
{
"url": "https://phpunit.de/sponsors.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-23T17:10:58+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for parsing CLI options",
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:08:49+00:00"
},
{
"name": "sebastian/code-unit",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
"reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
"source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:08:54+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:30:19+00:00"
},
{
"name": "sebastian/comparator",
"version": "4.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "55f4261989e546dc112258c7a75935a81a7ce382"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382",
"reference": "55f4261989e546dc112258c7a75935a81a7ce382",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/diff": "^4.0",
"sebastian/exporter": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T15:49:45+00:00"
},
{
"name": "sebastian/complexity",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
"reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.7",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for calculating the complexity of PHP code units",
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T15:52:27+00:00"
},
{
"name": "sebastian/diff",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"symfony/process": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff",
"udiff",
"unidiff",
"unified diff"
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:10:38+00:00"
},
{
"name": "sebastian/environment",
"version": "5.1.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "388b6ced16caa751030f6a69e588299fa09200ac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac",
"reference": "388b6ced16caa751030f6a69e588299fa09200ac",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T05:52:38+00:00"
},
{
"name": "sebastian/exporter",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9",
"reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-11-11T14:18:36+00:00"
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"ext-dom": "*",
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
},
{
"name": "sebastian/lines-of-code",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.6",
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library for counting the lines of code in PHP source code",
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-11-28T06:42:11+00:00"
},
{
"name": "sebastian/object-enumerator",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
"reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
"shasum": ""
},
"require": {
"php": ">=7.3",
"sebastian/object-reflector": "^2.0",
"sebastian/recursion-context": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:12:34+00:00"
},
{
"name": "sebastian/object-reflector",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
"source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:14:26+00:00"
},
{
"name": "sebastian/recursion-context",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-10-26T13:17:30+00:00"
},
{
"name": "sebastian/resource-operations",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:45:17+00:00"
},
{
"name": "sebastian/type",
"version": "2.3.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914",
"reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the types of the PHP type system",
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/2.3.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2021-06-15T12:49:02+00:00"
},
{
"name": "sebastian/version",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "c6c1022351a901512170118436c764e473f6de8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
"reference": "c6c1022351a901512170118436c764e473f6de8c",
"shasum": ""
},
"require": {
"php": ">=7.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-09-28T06:39:44+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": "^7.2 || ^8.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Arne Blankerts",
"email": "arne@blankerts.de",
"role": "Developer"
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
},
"funding": [
{
"url": "https://github.com/theseer",
"type": "github"
}
],
"time": "2021-07-28T10:34:58+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
@@ -4176,5 +6091,5 @@
"platform-overrides": {
"php": "8.0"
},
"plugin-api-version": "2.0.0"
"plugin-api-version": "2.2.0"
}
Executable → Regular
BIN
View File
Binary file not shown.
+7 -2
View File
@@ -36,16 +36,21 @@ body {
height: 130px;
}
#user_info button {
#user_info .btn {
width: 200px;
height: 50px;
margin: 10px 50px;
padding: 10px;
}
.center_ordered_items {
text-align: center;
}
.server-action{
padding-top: 16px;
padding-bottom: 16px;
}
.Entrance_ServerList {
width: 800px;
height: 64px;
+34 -16
View File
@@ -49,7 +49,7 @@ function getFriendlyErrorType($type)
return "{$type}";
}
function getExceptionTraceAsString($exception)
function getExceptionTraceAsString(\Throwable $exception)
{
//https://gist.github.com/abtris/1437966
$rtn = "";
@@ -96,6 +96,7 @@ function logError(string $err, string $errstr, string $errpath, array $trace)
$fdb = FileDB::db(ROOT . '/d_log/err_log.sqlite3', ROOT . '/f_install/sql/err_log.sql');
$date = date("Ymd_His");
$err =str_replace(ROOT, '{ROOT}', $errpath);
$errpath = str_replace(ROOT, '{ROOT}', $errpath);
$trace = array_map(function (string $text) {
return str_replace(ROOT, '{ROOT}', $text);
@@ -117,7 +118,7 @@ function logError(string $err, string $errstr, string $errpath, array $trace)
]);
}
function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, int $errline, array $errcontext=null)
function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, int $errline)
{
if (!(error_reporting() & $errno)) {
// This error code is not included in error_reporting, so let it fall
@@ -133,11 +134,12 @@ function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, in
$errfile . ':' . $errline,
getExceptionTraceAsString($e)
);
return true;
}
set_error_handler("\\sammo\\logErrorByCustomHandler");
function logExceptionByCustomHandler(\Throwable $e)
function logExceptionByCustomHandler(\Throwable $e, bool $withDie = true)
{
logError(
@@ -147,32 +149,48 @@ function logExceptionByCustomHandler(\Throwable $e)
getExceptionTraceAsString($e)
);
echo $e->getTraceAsString();
throw $e;
if($withDie){
echo $e->getTraceAsString();
throw $e;
}
}
set_exception_handler('\\sammo\\logExceptionByCustomHandler');
function getAPIExecutorClass($path){
function checkForFatal()
{
$error = error_get_last();
if($error === null){
return;
}
if (($error["type"]??0) == E_ERROR) {
logErrorByCustomHandler($error["type"], $error["message"], $error["file"], $error["line"]);
}
}
static $basePath = __NAMESPACE__.'\\API\\';
if(is_string($path)){
}
else if(is_array($path)){
register_shutdown_function("\\sammo\\checkForFatal");
function getAPIExecutorClass($path)
{
static $basePath = __NAMESPACE__ . '\\API\\';
if (is_string($path)) {
} else if (is_array($path)) {
$path = join('\\', $path);
}
else{
} else {
throw new \InvalidArgumentException("{$path}는 올바른 API 지시자가 아님");
}
$classPath = str_replace('/', '\\', $basePath.$path);
$classPath = str_replace('/', '\\', $basePath . $path);
if(class_exists($classPath)){
if (class_exists($classPath)) {
return $classPath;
}
throw new \InvalidArgumentException("{$path}는 올바른 API 경로가 아님");
}
function buildAPIExecutorClass($type, string $rootPath, array $args):\sammo\BaseAPI{
function buildAPIExecutorClass($type, string $rootPath, array $args): \sammo\BaseAPI
{
$class = getAPIExecutorClass($type);
return new $class($rootPath, $args);
}
}
+5
View File
@@ -2,6 +2,11 @@
namespace sammo;
if(!file_exists(__DIR__ . '/../vendor/autoload.php')){
http_response_code(503);
die('not_ready');
}
require(__DIR__ . '/../vendor/autoload.php');
if (!class_exists('\\sammo\\RootDB')) {
+16 -11
View File
@@ -31,8 +31,8 @@ CREATE TABLE `member` (
`NAME` VARCHAR(64) NOT NULL,
`PICTURE` VARCHAR(64) NULL DEFAULT 'default.jpg',
`IMGSVR` INT(1) NULL DEFAULT '0',
`acl` TEXT NOT NULL DEFAULT '{}' COMMENT 'json',
`penalty` TEXT NOT NULL DEFAULT '{}' COMMENT 'json',
`acl` TEXT NOT NULL DEFAULT '{}' COLLATE 'utf8mb4_bin',
`penalty` TEXT NOT NULL DEFAULT '{}' COLLATE 'utf8mb4_bin',
`GRADE` INT(1) NULL DEFAULT '1',
`REG_NUM` INT(3) NULL DEFAULT '0',
`REG_DATE` DATETIME NOT NULL,
@@ -43,9 +43,12 @@ CREATE TABLE `member` (
UNIQUE INDEX `ID` (`ID`),
UNIQUE INDEX `EMAIL` (`EMAIL`),
UNIQUE INDEX `kauth_id` (`oauth_id`),
INDEX `delete_after` (`delete_after`)
INDEX `delete_after` (`delete_after`),
CONSTRAINT `json1` CHECK (json_valid(`acl`)),
CONSTRAINT `json2` CHECK (json_valid(`penalty`))
)
ENGINE=Aria DEFAULT CHARSET=utf8mb4;
COLLATE='utf8mb4_general_ci'
ENGINE=Aria;
-- 로그인 로그 테이블
CREATE TABLE `member_log` (
@@ -53,12 +56,14 @@ CREATE TABLE `member_log` (
`member_no` INT(11) NOT NULL,
`date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`action_type` ENUM('reg','try_login','login','logout','oauth','change_pw','make_general','access_server','delete') NOT NULL,
`action` TEXT NULL DEFAULT NULL COMMENT 'JSON',
`action` TEXT NULL DEFAULT NULL COLLATE 'utf8mb4_bin',
PRIMARY KEY (`id`),
INDEX `action` (`member_no`, `action_type`, `date`),
INDEX `member` (`member_no`, `date`)
INDEX `member` (`member_no`, `date`),
CONSTRAINT `json` CHECK (json_valid(`action`))
)
ENGINE=Aria DEFAULT CHARSET=utf8mb4;
COLLATE='utf8mb4_general_ci'
ENGINE=Aria;
###################
# KV storage
@@ -69,9 +74,10 @@ CREATE TABLE if not exists `storage` (
`key` VARCHAR(40) NOT NULL,
`value` TEXT NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `key` (`namespace`, `key`)
UNIQUE INDEX `key` (`namespace`, `key`),
CONSTRAINT `json` CHECK (json_valid(`value`))
)
COLLATE='utf8mb4_general_ci'
COLLATE='utf8mb4_bin'
ENGINE=Aria;
CREATE TABLE `login_token` (
@@ -86,5 +92,4 @@ CREATE TABLE `login_token` (
INDEX `by_date` (`user_id`, `expire_date`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=Aria
;
ENGINE=Aria;
+1 -1
View File
@@ -14,7 +14,7 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
[$turntime, $tnmt_time] = $gameStor->getValuesAsArray(['turntime','tnmt_time']);
$plock = $db->queryFirstField('SELECT plock FROM plock');
$plock = $db->queryFirstField('SELECT plock FROM plock WHERE `type` ="GAME"');
?>
<!DOCTYPE html>
<html>
+1
View File
@@ -72,6 +72,7 @@ switch ($btn) {
case "30분턴": $turnterm = 30; break;
case "60분턴": $turnterm = 60; break;
case "120분턴": $turnterm = 120; break;
default: throw new \Exception("알 수 없는 턴 기간");
}
$oldunit = $admin['turnterm'] * 60;
$unit = $turnterm * 60;
+4 -4
View File
@@ -59,10 +59,10 @@ $db = DB::db();
if ($general['block'] > 0) {
$style .= "background-color:red;";
}
if ($general['npc'] >= 2) {
$style .= "color:cyan;";
} elseif ($general['npc'] == 1) {
$style .= "color:skyblue;";
$npcColor = getNPCColor($general['npc']);
if($npcColor !== null){
$style .= "color:{$npcColor};";
}
echo "
+4 -7
View File
@@ -70,13 +70,10 @@ function colorBlockedName($general)
if ($general['block'] > 0) {
$style .= "background-color:red;";
}
if ($general['npc'] >= 2) {
$style .= "color:cyan;";
} elseif ($general['npc'] == 1) {
$style .= "color:skyblue;";
}
if ($general['con'] > $conlimit) {
$style .= "color:red;";
$npcColor = getNPCColor($general['npc']);
if($npcColor !== null){
$style .= "color:{$npcColor};";
}
echo "
+2
View File
@@ -5,7 +5,9 @@ namespace sammo;
include "lib.php";
include "func.php";
/** @var int */
$type = Util::getPost('type', 'int', 0);
/** @var int */
$type2 = Util::getPost('type2', 'int', 0);
if ($type < 0 || $type > 17) {
+2
View File
@@ -95,6 +95,8 @@ $sel[$type] = "selected";
case 7:
$state = "<font color=green>불가침</font>";
break;
default:
throw new \Exception("알 수 없는 외교 상태: {$dip['state']}");
}
$date = TimeUtil::now();
+4 -3
View File
@@ -25,8 +25,9 @@ foreach ($db->queryFirstColumn(
CheckHall($generalNo);
}
$inheritPointManager = InheritancePointManager::getInstance();
foreach(General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){
$genObj->mergeTotalInheritancePoint(true);
applyInheritanceUser($genObj->getVar('owner'));
$genObj->clearInheritancePoint();
$inheritPointManager->mergeTotalInheritancePoint($genObj, true);
$inheritPointManager->applyInheritanceUser($genObj->getVar('owner'));
$inheritPointManager->clearInheritancePoint($genObj);
}
+46 -30
View File
@@ -2,6 +2,8 @@
namespace sammo;
use sammo\Enums\RankColumn;
include "lib.php";
include "func.php";
@@ -24,32 +26,26 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates');
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1136" />
<meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 명장일람</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/hallOfFame.css') ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('ts', 'common') ?>
<?= WebUtil::printDist('ts', ['common', 'bestGeneral']) ?>
</head>
<body>
<table align=center width=1100 class='tb_layout bg0'>
<tr>
<td>명 장 일 람<br><?= closeButton() ?></td>
</tr>
</table>
<table align=center width=1100 class='tb_layout bg0'>
<form name=form1 action=a_bestGeneral.php method=post>
<tr>
<td align=center>
<input type=submit name=btn value='유저 보기'>
<div id="container" class="bg0">
<div class="row gx-0">
<div class="col">명 장 일 람<br><?= closeButton() ?></div>
</div>
<div class="row gx-0">
<div class="col center">
<form name=form1 action=a_bestGeneral.php method=get><input type=submit name=btn value='유저 보기'>
<input type=submit name=btn value='NPC 보기'>
</td>
</tr>
</form>
</table>
<div style="margin:auto;width:1100px;">
</form>
</div>
</div>
<?php
$ownerNameList = [];
@@ -209,6 +205,32 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates');
}
return $v;
}],
["유 산 소 모 량", "int", function ($v) use ($gameStor) {
$v['value'] = $v[RankColumn::inherit_point_spent->value];
if ($gameStor->isunited) {
return $v;
}
$v['nationName'] = '???';
$v['pictureFullPath'] = GetImageURL(0) . "/default.jpg";
$v['name'] = '???';
$v['ownerName'] = null;
$v['bgColor'] = GameConst::$basecolor4;
$v['fgColor'] = newColor($v['bgColor']);
return $v;
}],
["유 산 획 득 량", "int", function ($v) use ($gameStor) {
$v['value'] = $v[RankColumn::inherit_point_earned->value];
if ($gameStor->isunited) {
return $v;
}
$v['nationName'] = '???';
$v['pictureFullPath'] = GetImageURL(0) . "/default.jpg";
$v['name'] = '???';
$v['ownerName'] = null;
$v['bgColor'] = GameConst::$basecolor4;
$v['fgColor'] = newColor($v['bgColor']);
return $v;
}],
];
$generals = [];
@@ -274,10 +296,6 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates');
'generals' => array_slice($typeGenerals, 0, min(10, $validCnt))
]);
}
?>
</div>
<div style="margin:auto;width:1100px;margin-top:5px;">
<?php
//유니크 아이템 소유자
$itemTypes = [
'horse' => '명 마',
@@ -369,15 +387,13 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates');
]);
}
?>
<div class="row gx-0">
<div class="col"><?= closeButton() ?></div>
</div>
<div class="row bg0 gx-0">
<div class="col bg0"><?= banner() ?></div>
</div>
</div>
<table align=center width=1100 class='tb_layout bg0'>
<tr>
<td><?= closeButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
</body>
</html>
+2 -2
View File
@@ -55,7 +55,7 @@ increaseRefresh("왕조일람", 1);
<tr>
<td style="background-color:#333333;" align=center colspan=8>
<font size=5>현재 (<?= $year ?>年 <?= $month ?>月)</font>
<a href="a_history.php"><button type='button'>역사 보기</button></a>
<a href="v_history.php"><button type='button'>역사 보기</button></a>
</td>
</tr>
</table>
@@ -75,7 +75,7 @@ increaseRefresh("왕조일람", 1);
<a href="a_emperior_detail.php?select=<?= $emperior['no'] ?>"><button type='button'>자세히</button></a>
<?php if ($emperior['server_id']) : ?>
<a href="a_history.php?serverID=<?= $emperior['server_id'] ?>"><button type='button'>역사 보기</button></a>
<a href="v_history.php?serverID=<?= $emperior['server_id'] ?>"><button type='button'>역사 보기</button></a>
<?php endif ?>
</td>
</tr>
+3 -2
View File
@@ -173,8 +173,9 @@ $serverID = $emperior['server_id'] ?? ($emperior['serverID'] ?? null);
if (!$nation['nation'] ?? null) {
continue;
}
$nation += Json::decode($nation['data']);
$nation = array_merge(Json::decode($nation['data']), $nation);
/** @var array $nation */
$nation['typeName'] = getNationType($nation['type']);
$nation['levelName'] = getNationLevel($nation['level']);
/** @var int[]|null $nationGenerals */
@@ -200,7 +201,7 @@ $serverID = $emperior['server_id'] ?? ($emperior['serverID'] ?? null);
}
if (key_exists('aux', $nation) && !is_array($nation['aux'])) {
$nation += Json::decode($nation['aux']);
$nation = array_merge(Json::decode($nation['aux']), $nation);
}
echo $templates->render('oldNation', $nation);
+2 -7
View File
@@ -155,13 +155,7 @@ if ($gameStor->isunited) {
if ($general['npc'] >= 2) {
$name = "<font color=cyan>{$general['name']}</font>";
} elseif ($general['npc'] == 1) {
$name = "<font color=skyblue>{$general['name']}</font>";
} else {
$name = "{$general['name']}";
}
$name = formatName($general['name'], $general['npc']);
if (key_exists($general['owner'], $ownerNameList)) {
$name = $name . '<br><small>(' . $ownerNameList[$general['owner']] . ')</small>';
@@ -178,6 +172,7 @@ if ($gameStor->isunited) {
data-general-strength='{$general['strength']}'
data-general-intel='{$general['intel']}'
data-is-npc='" . ($general['npc'] >= 2 ? 'true' : 'false') . "'
data-npc-type='{$general['npc']}'
>
<td align=center><img class='generalIcon' width='64' height='64' src='{$imageTemp}/{$general['picture']}'></img></td>
<td align=center>$name</td>
+20 -23
View File
@@ -44,22 +44,21 @@ if ($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx] ?? [])) {
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1136" />
<meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 명예의 전당</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/hallOfFame.css') ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('ts', ['common', 'hallOfFame']) ?>
</head>
<body>
<table align=center width=1100 class='tb_layout bg0'>
<tr>
<td>명 예 의 전 당<br><?= closeButton() ?></td>
</tr>
<tr>
<td>
<div id="container" class="bg0">
<div class="row gx-0">
<div class="col">명 예 의 전 당<br><?= closeButton() ?></div>
</div>
<div class="row gx-0">
<div class="col center">
시나리오 검색 : <select id="by_scenario" name="by_scenario">
<?php foreach ($scenarioList as $iterSeasonIdx => $subScenarioList) : ?>
<option data-season="<?= $iterSeasonIdx ?>" value="" <?= ($iterSeasonIdx == $seasonIdx && $scenarioIdx === null) ? "selected='selected'" : '' ?>>* 시즌 : <?= $iterSeasonIdx ?> 종합 *</option>
@@ -69,10 +68,8 @@ if ($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx] ?? [])) {
<?php endforeach; ?>
?>
</select>
</td>
</tr>
</table>
<div style="margin:auto;width:1100px;">
</div>
</div>
<?php
$types = [
'experience' => ['명 성', 'int'],
@@ -113,7 +110,8 @@ if ($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx] ?? [])) {
$hallResult = array_map(function ($general) use ($typeValue, $ownerNameList) {
$aux = Json::decode($general['aux']);
$general += $aux;
/** @var array $general */
$general = array_merge($aux, $general);
if (key_exists($general['owner'], $ownerNameList)) {
$general['ownerName'] = $ownerNameList[$general['owner']];
@@ -121,10 +119,11 @@ if ($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx] ?? [])) {
if (!key_exists('bgColor', $general)) {
if (!key_exists('color', $general)) {
$general['bgColor'] = GameConst::$basecolor4;
$color = GameConst::$basecolor4;
} else {
$general['bgColor'] = $general['color'];
$color = $general['color'];
}
$general['bgColor'] = $color;
}
if (!key_exists('fgColor', $general)) {
@@ -156,15 +155,13 @@ if ($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx] ?? [])) {
]);
}
?>
<div class="row gx-0">
<div class="col"><?= closeButton() ?></div>
</div>
<div class="row bg0 gx-0">
<div class="col bg0"><?= banner() ?></div>
</div>
</div>
<table align=center width=1100 class='tb_layout bg0'>
<tr>
<td><?= closeButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
</body>
</html>
-215
View File
@@ -1,215 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$btn = Util::getReq('btn');
$yearmonth = Util::getReq('yearmonth', 'int');
$serverID = Util::getReq('serverID', 'string', null);
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if (!$serverID) {
$serverID = UniqueConst::$serverID;
}
if ($serverID === UniqueConst::$serverID) {
increaseRefresh("연감", 1);
}
$admin = $gameStor->getValues(['startyear', 'year', 'month', 'map_theme']);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner = %i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
[$s_year, $s_month] = $db->queryFirstList('SELECT year, month FROM ng_history WHERE server_id = %s ORDER BY year ASC, month ASC LIMIT 1', $serverID);
$s = $s_year * 12 + $s_month;
if ($s_year === null) {
echo '인자 에러';
exit();
}
[$e_year, $e_month] = $db->queryFirstList('SELECT year, month FROM ng_history WHERE server_id = %s ORDER BY year DESC, month DESC LIMIT 1', $serverID);
$e = $e_year * 12 + $e_month;
if ($serverID !== UniqueConst::$serverID) {
$mapTheme = $db->queryFirstField('SELECT map FROM ng_games WHERE server_id=%s', $serverID) ?: 'che';
} else {
$mapTheme = $admin['map_theme'] ?? 'che';
}
//FIXME: $yearmonth가 올바르지 않을 경우에 처리가 필요.
if ($serverID !== UniqueConst::$serverID && !$yearmonth) {
$year = $s_year;
$month = $s_month;
} else if (!$yearmonth) {
$year = $admin['year'];
$month = $admin['month'] - 1;
} else {
$year = intdiv($yearmonth, 100);
$month = $yearmonth % 100;
if ($btn == "◀◀ 이전달") {
$month -= 1;
} elseif ($btn == "다음달 ▶▶") {
$month += 1;
}
}
$now = ($year * 12) + $month;
if ($now < $s) {
$now = $s;
}
if ($now > $e) {
$now = $e;
}
$year = intdiv($now, 12);
$month = $now % 12;
if ($month <= 0) {
$year -= 1;
$month += 12;
}
$history = $db->queryFirstRow('SELECT * FROM ng_history WHERE server_id = %s AND year = %i AND month = %i', $serverID, $year, $month);
$nations = Json::decode($history['nations']);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 연감</title>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS("js/map/theme_{$mapTheme}.js") ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/map.css') ?>
<?= WebUtil::printCSS('css/history.css') ?>
<?= WebUtil::printDist('ts', ['common', 'history']) ?>
<script>
var startYear = <?= $s_year ?>;
var startMonth = <?= $s_month ?>;
var lastYear = <?= $e_year ?>;
var lastMonth = <?= $e_month ?>;
var selectYear = <?= $year ?>;
var selectMonth = <?= $month ?>;
var nations = <?= $nations ? $history['nations'] : '{}' ?>;
</script>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td>연 감<br><?= closeButton() ?></td>
</tr>
<tr>
<td>
<form name=form1 method=post>
연월 선택 :
<input type=submit name=btn value="◀◀ 이전달">
<select id='yearmonth' name=yearmonth size=1>
<option selected='selected'><?= $year ?>년 <?= $month ?>월</option>
<option><?= $e_year ?>년 12월</option>
</select>
<input type=submit name=btn value='조회하기'>
<input type=submit name=btn value="다음달 ▶▶">
</form>
</td>
</tr>
</table>
<table align=center width=1000 height=520 class='tb_layout bg0'>
<thead>
<tr>
<th colspan=5 align=center class='bg1'>중 원 지 도</th>
</tr>
</thead>
<tbody>
<tr height=520>
<td width=698>
<?= getMapHtml($mapTheme) ?>
</td>
<td id='nation_list_frame'>
<table id='nation_list'>
<thead>
<tr>
<th width=130>국명</th>
<th width=70>국력</th>
<th width=45>장수</th>
<th width=45>속령</th>
</tr>
</thead>
<tbody>
<?php foreach ($nations as $nation) : ?>
<tr>
<td><span style='color:<?= newColor($nation['color']) ?>;background-color:<?= $nation['color'] ?>'><?= $nation['name'] ?></td>
<td style='text-align:right'><?= number_format($nation['power']) ?></td>
<td style='text-align:right'><?= number_format($nation['gennum']) ?></td>
<td style='text-align:right'><?= number_format(count($nation['cities'] ?? [])) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot></tfoot>
</table>
</td>
</tr>
<tr>
<th colspan=5 align=center class='bg1'>중 원 정 세</th>
</tr>
<tr>
<td colspan=5 valign=top>
<?= formatHistoryToHTML(Json::decode($history['global_history'])) ?>
</td>
</tr>
<tr>
<th colspan=5 align=center class='bg1'>장 수 동 향</th>
</tr>
<tr>
<td colspan=5 valign=top>
<?= formatHistoryToHTML(Json::decode($history['global_action'])) ?>
</td>
</tr>
</tbody>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td><?= closeButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
<script>
window.serverNick = '<?= DB::prefix() ?>';
window.serverID = '<?= UniqueConst::$serverID ?>';
reloadWorldMap({
targetJson: 'j_map_history.php?year=<?= $year ?>&month=<?= $month ?>&serverID=<?= $serverID ?>',
showMe: false,
neutralView: true,
useCachedMap: false,
year: <?= $year ?>,
month: <?= $month ?>,
});
</script>
</body>
</html>
+5 -10
View File
@@ -10,7 +10,7 @@ $userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['killturn', 'autorun_user', 'turnterm']);
increaseRefresh("세력일람", 2);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
@@ -33,6 +33,7 @@ if ($con >= 2) {
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('ts', ['common', 'extKingdoms']) ?>
<?= WebUtil::printStaticValues($gameStor->getValues(['killturn', 'autorun_user', 'turnterm'])) ?>
</head>
<body>
@@ -110,7 +111,7 @@ if ($con >= 2) {
}
$chief = $chiefs[$chiefLevel] ?? ['name' => '-', 'npc' => 0];
$officerLevelText = getOfficerLevelText($chiefLevel, $nation['level']);
$chiefText = getColoredName($chief['name'], $chief['npc']);
$chiefText = formatName($chief['name'], $chief['npc']);
echo "<td class='center bg1'>{$officerLevelText}</td>
<td class='center'>{$chiefText}</td>";
}
@@ -144,13 +145,7 @@ if ($con >= 2) {
<tr>
<td colspan=8> 장수 일람 : ";
foreach ($generals as $general) {
if ($general['npc'] >= 2) {
echo "<font color=cyan>{$general['name']}</font>, ";
} elseif ($general['npc'] == 1) {
echo "<font color=skyblue>{$general['name']}</font>, ";
} else {
echo "{$general['name']}, ";
}
echo formatName($general['name'], $general['npc']).', ';
}
echo "
</td>
@@ -183,7 +178,7 @@ if ($con >= 2) {
<tr>
<td colspan=5> 장수 일람 : ";
foreach ($nations[0]['generals'] as $general) {
$generalText = getColoredName($general['name'], $general['npc']);
$generalText = formatName($general['name'], $general['npc']);
echo "{$generalText}, ";
}
echo "
+1 -1
View File
@@ -111,7 +111,7 @@ $sel[$type] = "selected";
</tr>
<?php foreach ($generalList as $general) : ?>
<tr>
<td align=center><?= getColoredName($general['name'], $general['npc']) ?></td>
<td align=center><?= formatName($general['name'], $general['npc']) ?></td>
<td align=center><?= $general['owner_name'] ?></td>
<td align=center>Lv <?= $general['explevel'] ?></td>
<td align=center><?= $nationName[$general['nation']] ?></td>
-88
View File
@@ -1,88 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("세력도", 2);
TurnExecutionHelper::executeAllCommand();
$mapTheme = $gameStor->map_theme ?? 'che';
$me = $db->queryFirstRow('SELECT con,turntime from general where owner=%i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 세력도</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printCSS('css/normalize.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/map.css') ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('d_shared/base_map.js') ?>
<?= WebUtil::printDist('ts', ['common', 'map']) ?>
<script>
window.serverNick = '<?= DB::prefix() ?>';
window.serverID = '<?= UniqueConst::$serverID ?>';
$(function() {
reloadWorldMap({
neutralView: true,
showMe: true,
useCachedMap: true
});
});
</script>
</head>
<body>
<table align=center width=1200 class='tb_layout bg0'>
<tr>
<td>세 력 도<br><?= closeButton() ?></td>
</tr>
</table>
<table align=center width=1200 height=520 class='tb_layout bg0'>
<tr height=520>
<td width=498 valign=top>
<?= formatHistoryToHTML(getGlobalActionLogRecent(34)) ?>
</td>
<td width=698>
<?= getMapHtml($mapTheme) ?>
</td>
</tr>
<tr>
<td colspan=2 valign=top>
<?= formatHistoryToHTML(getGlobalHistoryLogRecent(34)) ?>
</td>
</tr>
</table>
<table align=center width=1200 class='tb_layout bg0'>
<tr>
<td><?= closeButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
</body>
</html>
+6 -1
View File
@@ -5,4 +5,9 @@ namespace sammo;
include "lib.php";
include "func.php";
APIHelper::launch(dirname(__FILE__));
$eParams = $_GET;
if(key_exists('path', $eParams)){
unset($eParams['path']);
}
APIHelper::launch(dirname(__FILE__), $_GET['path']??'', $eParams, true);
+67 -76
View File
@@ -74,7 +74,7 @@ if ($testGeneralNationID != $nationID) {
$gen = 0;
}
if ($btn == '정렬하기') {
if ($btn == '정렬') {
$gen = 0;
}
@@ -118,100 +118,91 @@ $showGeneral = General::createGeneralObjFromDB($gen);
<title><?= UniqueConst::$serverName ?>: 감찰부</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<meta name="viewport" content="width=500" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('ts', ['common']) ?>
<?= WebUtil::printDist('ts', ['common', 'battleCenter']) ?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td>감 찰 부<br><?= closeButton() ?></td>
</tr>
<tr>
<td>
<form name=form1 method=post>
<div id="container" class="bg0">
<div class="row gx-0">
<div class="col">감 찰 부<br><?= closeButton() ?></div>
</div>
<div class="row gx-0">
<div class="col-12" style="border-left: solid 1px gray; border-right:solid 1px gray;">
<form name=form1 method=get>
정렬순서 :
<select name='query_type' size=1>
<?php foreach ($queryMap as $queryType => [$queryTypeText,]) : ?>
<option <?= $queryType == $reqQueryType ? 'selected' : '' ?> value='<?= $queryType ?>'><?= $queryTypeText ?></option>
<?php endforeach; ?>
</select>
<input type=submit name=btn value='정렬하기'>
<input type=submit name=btn value='정렬'>
대상장수 :
<select name=gen size=1>
<?php foreach ($generalBasicList as $general) : ?>
<option <?= $gen == $general['no'] ? 'selected' : '' ?> value='<?= $general['no'] ?>'><?= $general['officer_level'] > 4 ? "*{$general['name']}*" : $general['name'] ?> (<?= substr($general['turntime'], 14, 5) ?>)</option>
<?php endforeach; ?>
</select>
<input type=submit name=btn value='조회하기'>
<input type=submit name=btn value='조회'>
</form>
</td>
</tr>
</table>
<table width=1000 align=center class='tb_layout bg0'>
<tr>
<td width=50% align=center class='bg1'>
<font color=skyblue size=3>장 수 정 보</font>
</td>
<td width=50% align=center class='bg1'>
<font color=orange size=3>장 수 열 전</font>
</td>
</tr>
<tr>
<td valign=top>
<?php generalInfo($showGeneral);
generalInfo2($showGeneral); ?>
</td>
<td valign=top>
<?= formatHistoryToHTML(getGeneralHistoryLogAll($gen)) ?>
</td>
</tr>
<tr>
<td align=center class='bg1'>
<font color=orange size=3>전투 기록</font>
</td>
<td align=center class='bg1'>
<font color=orange size=3>전투 결과</font>
</td>
</tr>
<tr>
<td valign=top>
<?= formatHistoryToHTML(getBattleDetailLogRecent($gen, 24)) ?>
</td>
<td valign=top>
<?= formatHistoryToHTML(getBattleResultRecent($gen, 24)) ?>
</td>
</tr>
<?php if ($showGeneral->getNPCType() > 1 || $permission >= 2) : ?>
<tr>
<td align=center class='bg1'>
<font color=orange size=3>개인 기록</font>
</td>
<td align=center class='bg1'>
<font color=orange size=3>&nbsp;</font>
</td>
</tr>
<tr>
<td valign=top>
<?= formatHistoryToHTML(getGeneralActionLogRecent($gen, 24)) ?>
</td>
<td valign=top>
</td>
</tr>
<?php endif; ?>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td><?= closeButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
</div>
<div class="col col-12 col-md-6">
<div class="row mx-0">
<div class="col bg1 header-cell" style="color:skyblue">장수 정보</div>
</div>
<div class="row">
<div class="col"><?php generalInfo($showGeneral); ?><?php generalInfo2($showGeneral); ?></div>
</div>
</div>
<div class="col col-12 col-md-6">
<div class="row mx-0">
<div class="col bg1 header-cell">장수 열전</div>
</div>
<div class="row">
<div class="col"><?= formatHistoryToHTML(getGeneralHistoryLogAll($gen)) ?></div>
</div>
</div>
<div class="col col-12 col-md-6">
<div class="row mx-0">
<div class="col bg1 header-cell">전투 기록</div>
</div>
<div class="row">
<div class="col"><?= formatHistoryToHTML(getBattleDetailLogRecent($gen, 24)) ?></div>
</div>
</div>
<div class="col col-12 col-md-6">
<div class="row mx-0">
<div class="col bg1 header-cell">전투 결과</div>
</div>
<div class="row">
<div class="col"><?= formatHistoryToHTML(getBattleResultRecent($gen, 24)) ?></div>
</div>
</div>
<?php if ($showGeneral->getNPCType() > 1 || $permission >= 2) : ?>
<div class="col col-12 col-md-6">
<div class="row mx-0">
<div class="col bg1 header-cell">개인 기록</div>
</div>
<div class="row">
<div class="col"><?= formatHistoryToHTML(getGeneralActionLogRecent($gen, 24)) ?></div>
</div>
</div>
<?php endif; ?>
</div>
<div class="row gx-0">
<div class="col "><?= backButton() ?></div>
</div>
<div class="row bg0 gx-0">
<div class="col bg0"><?= banner() ?></div>
</div>
</div>
</body>
</html>
+118 -91
View File
@@ -2,6 +2,8 @@
namespace sammo;
use sammo\Enums\RankColumn;
include "lib.php";
include "func.php";
//로그인 검사
@@ -16,17 +18,11 @@ TurnExecutionHelper::executeAllCommand();
$generalID = $session->generalID;
//NOTE: general_id만 빼기 귀찮음.
$myBet = $db->queryFirstList('SELECT * FROM betting WHERE general_id = %i', $generalID);
$myBet = array_splice($myBet, -16);
$globalBet = $db->queryFirstList('SELECT * FROM betting WHERE general_id = 0');
$globalBet = array_splice($globalBet, -16);
$me = $db->queryFirstRow('SELECT no,tournament,con,turntime from general where owner=%i', $userID);
$myBetTotal = array_sum($myBet);
$globalBetTotal = array_sum($globalBet);
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'develcost']);
$con = checkLimit($me['con']);
@@ -36,40 +32,74 @@ if ($con >= 2) {
}
switch ($admin['tnmt_type']) {
default:
throw new \RuntimeException('Invalid tnmt_type');
case 0:
$tnmt_type = "<font color=cyan>전력전</font>";
case convertTournamentType('전력전'):
$tnmt_type = "전력전";
$color = "cyan";
$tp = "total";
$tp2 = "종합";
$tp3 = "total";
break;
case 1:
$tnmt_type = "<font color=cyan>통솔전</font>";
case convertTournamentType('통솔전'):
$tnmt_type = "통솔전";
$color = "cyan";
$tp = "leadership";
$tp2 = "통솔";
$tp3 = "leadership";
break;
case 2:
$tnmt_type = "<font color=cyan>일기토</font>";
case convertTournamentType('일기토'):
$tnmt_type = "일기토";
$color = "cyan";
$tp = "strength";
$tp2 = "무력";
$tp3 = "strength";
break;
case 3:
$tnmt_type = "<font color=cyan>설전</font>";
case convertTournamentType('설전'):
$tnmt_type = "설전";
$color = "cyan";
$tp = "intel";
$tp2 = "지력";
$tp3 = "intel";
break;
default:
throw new \RuntimeException('Invalid tnmt_type');
}
$bettingID = $gameStor->last_tournament_betting_id ?? 0;
$myBet = [];
$globalBet = [];
if ($bettingID != 0) {
$betting = $bettingID != 0 ? new Betting($bettingID) : null;
$info = $betting->getInfo();
foreach ($db->queryAllLists(
'SELECT general_id, user_id, amount, betting_type FROM ng_betting WHERE betting_id = %i',
$bettingID
) as [$betGeneralID, $userID, $amount, $bettingTypeKey]) {
$bettingKey = Json::decode($bettingTypeKey)[0];
if ($betGeneralID == $generalID) {
$myBet[$bettingKey] = $amount;
}
if (key_exists($bettingKey, $globalBet)) {
$globalBet[$bettingKey] += $amount;
} else {
$globalBet[$bettingKey] = $amount;
}
}
} else {
$info = getDummyBettingInfo($tnmt_type);
}
$myBetTotal = array_sum($myBet);
$globalBetTotal = array_sum($globalBet);
$str1 = getTournament($admin['tournament']);
$str2 = getTournamentTime();
if ($str2) {
$str2 = ', ' . $str2;
}
$str3 = getTournamentTerm();
$str3 = getTournamentTermText();
if ($str3) {
$str3 = ', ' . $str3;
}
@@ -90,6 +120,11 @@ if ($str3) {
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('ts', ['common', 'betting']) ?>
<?= WebUtil::printStaticValues([
'staticValues'=>[
'bettingID'=> $bettingID
]
])?>
</head>
<body>
@@ -104,7 +139,7 @@ if ($str3) {
</tr>
<tr>
<td colspan=16 align=center>
<font color=white size=6><?= $tnmt_type ?> (<?= $str1 . $str2 . $str3 ?>)</font>
<font color=white size=6><span style="color:<?= $color ?>"><?= $tnmt_type ?></span> (<?= $str1 . $str2 . $str3 ?>)</font>
</td>
</tr>
<tr>
@@ -132,11 +167,8 @@ if ($str3) {
if ($general['name'] == "") {
$general['name'] = "-";
}
if ($general['npc'] >= 2) {
$general['name'] = "<font color=cyan>" . $general['name'] . "</font>";
} elseif ($general['npc'] == 1) {
$general['name'] = "<font color=skyblue>" . $general['name'] . "</font>";
}
$general['name'] = formatName($general['name'], $general['npc']);
echo "<td colspan=16>{$general['name']}</td>";
}
@@ -162,11 +194,7 @@ if ($str3) {
if ($general['name'] == "") {
$general['name'] = "-";
}
if ($general['npc'] >= 2) {
$general['name'] = "<font color=cyan>" . $general['name'] . "</font>";
} elseif ($general['npc'] == 1) {
$general['name'] = "<font color=skyblue>" . $general['name'] . "</font>";
}
$general['name'] = formatName($general['name'], $general['npc']);
if ($general['win'] > 0) {
$line[$i] = "<font color=red>";
$cent[intdiv($i, 2)] = "<font color=red>";
@@ -208,11 +236,7 @@ if ($str3) {
if ($general['name'] == "") {
$general['name'] = "-";
}
if ($general['npc'] >= 2) {
$general['name'] = "<font color=cyan>" . $general['name'] . "</font>";
} elseif ($general['npc'] == 1) {
$general['name'] = "<font color=skyblue>" . $general['name'] . "</font>";
}
$general['name'] = formatName($general['name'], $general['npc']);
if ($general['win'] > 0) {
$line[$i] = "<font color=red>";
$cent[intdiv($i, 2)] = "<font color=red>";
@@ -254,11 +278,7 @@ if ($str3) {
if ($general['name'] == "") {
$general['name'] = "-";
}
if ($general['npc'] >= 2) {
$general['name'] = "<font color=cyan>" . $general['name'] . "</font>";
} elseif ($general['npc'] == 1) {
$general['name'] = "<font color=skyblue>" . $general['name'] . "</font>";
}
$general['name'] = formatName($general['name'], $general['npc']);
if ($general['win'] > 0) {
$line[$i] = "<font color=red>";
$cent[intdiv($i, 2)] = "<font color=red>";
@@ -280,7 +300,6 @@ if ($str3) {
for ($i = 0; $i < 8; $i++) {
echo "<td colspan=2>{$gen[$i]}</td>";
}
echo "
</tr>
<tr align=center>";
@@ -288,7 +307,7 @@ if ($str3) {
for ($i = 0; $i < 8; $i++) {
$cent[$i] = "<font color=white>";
}
$generalList = $db->query('SELECT npc,name,win from tournament where grp>=20 order by grp, grp_no LIMIT 16');
$generalList = $db->query('SELECT npc,name,win,leadership,strength,intel,leadership+strength+intel as total from tournament where grp>=20 order by grp, grp_no LIMIT 16');
while (count($generalList) < 16) {
$generalList[] = [
'name' => '-',
@@ -300,11 +319,7 @@ if ($str3) {
if ($general['name'] == "") {
$general['name'] = "-";
}
if ($general['npc'] >= 2) {
$general['name'] = "<font color=cyan>" . $general['name'] . "</font>";
} elseif ($general['npc'] == 1) {
$general['name'] = "<font color=skyblue>" . $general['name'] . "</font>";
}
$general['name'] = formatName($general['name'], $general['npc']);
if ($general['win'] > 0) {
$line[$i] = "<font color=red>";
$cent[intdiv($i, 2)] = "<font color=red>";
@@ -312,6 +327,11 @@ if ($str3) {
$line[$i] = "<font color=white>";
}
$gen[$i] = $general['name'];
if (array_key_exists($tp, $general)) {
$stat[$i] = $general[$tp];
} else {
$stat[$i] = "-";
}
}
for ($i = 0; $i < 8; $i++) {
$cent[$i] = $cent[$i] . "┻" . "</font>";
@@ -319,45 +339,48 @@ if ($str3) {
$line[$i * 2 + 1] = $line[$i * 2 + 1] . "━━┓" . "</font>";
echo "<td colspan=2>{$line[$i * 2]}{$cent[$i]}{$line[$i * 2 + 1]}</td>";
}
echo "
</tr>
<tr align=center>";
for ($i = 0; $i < 16; $i++) {
echo "<td width=70>{$gen[$i]}</td>";
}
$bet = [];
$gold = [];
for ($i = 0; $i < 16; $i++) {
if ($globalBet[$i] == 0) {
$bet[$i] = "∞";
} else {
$bet[$i] = round($globalBetTotal / $globalBet[$i], 2);
}
}
for ($i = 0; $i < 16; $i++) {
if (!is_numeric($bet[$i])) {
$gold[$i] = 0;
} else {
$gold[$i] = Util::round($myBet[$i] * $bet[$i]);
}
}
?>
</tr>
<tr align=center>
<?php for ($i = 0; $i < 16; $i++) { ?>
<td width=70><?= $gen[$i] ?></td>
<?php } ?>
</tr>
<tr align=center>
<?php for ($i = 0; $i < 16; $i++) { ?>
<td width=70 style="font-size: 14px"><?= $stat[$i] ?></td>
<?php } ?>
</tr>
</table>
<table align=center width=1120 class='tb_layout bg0'>
<table align=center width=1120 style="table-layout: fixed" class='tb_layout bg0'>
<tr align=center>
<td height=10 colspan=16></td>
</tr>
<?php
$bet = [];
$gold = [];
$keyMap = [];
foreach ($info->candidates as $key => $candidate) {
$keyMap[$candidate->aux['idx']] = $key;
}
foreach ($globalBet as $key => $amount) {
if ($amount == 0) {
$bet[$key] = "∞";
$gold[$key] = 0;
} else {
$rewardRatio = round($globalBetTotal / $amount, 2);
$bet[$key] = $rewardRatio;
$gold[$key] = $rewardRatio * ($myBet[$key] ?? 0);
}
}
echo "
<tr align=center>";
for ($i = 0; $i < 16; $i++) {
echo "<td width=70><font color=skyblue>{$bet[$i]}</font></td>";
foreach (range(0, 15) as $i) {
$amount = $bet[$keyMap[$i] ?? -1] ?? 0;
echo "<td width=70><font color=skyblue>{$amount}</font></td>";
}
?>
</tr>
@@ -381,8 +404,9 @@ if ($str3) {
</tr>
<tr align=center>
<?php
for ($i = 0; $i < 16; $i++) {
echo "<td><font color=orange>{$myBet[$i]}</font></td>";
foreach (range(0, 15) as $i) {
$amount = $myBet[$keyMap[$i] ?? -1] ?? 0;
echo "<td><font color=orange>{$amount}</font></td>";
}
?>
</tr>
@@ -406,8 +430,9 @@ if ($str3) {
</tr>
<tr align=center>
<?php
for ($i = 0; $i < 16; $i++) {
echo "<td><font color=cyan>{$gold[$i]}</font></td>";
foreach (range(0, 15) as $i) {
$amount = $gold[$keyMap[$i] ?? -1] ?? 0;
echo "<td><font color=cyan>{$amount}</font></td>";
}
echo "
@@ -418,10 +443,11 @@ if ($str3) {
echo "
<tr align=center>";
for ($i = 0; $i < 16; $i++) {
foreach (range(0, 15) as $i) {
$key = $keyMap[$i] ?? -1;
echo "
<td>
<select size=1 id='target_{$i}' style=color:white;background-color:black;>
<select size=1 id='target_{$key}' style=color:white;background-color:black;>
<option style=color:white; value=10>금10</option>
<option style=color:white; value=20>금20</option>
<option style=color:white; value=50>금50</option>
@@ -437,9 +463,10 @@ if ($str3) {
</tr>
<tr align=center>";
for ($i = 0; $i < 16; $i++) {
foreach (range(0, 15) as $i) {
$key = $keyMap[$i] ?? -1;
echo "
<td><input type=button class='submitBtn' data-target='{$i}' value=베팅! style=width:100%;color:white;background-color:black;></td>";
<td><input type=button class='submitBtn' data-target='{$key}' value=베팅! style=width:100%;color:white;background-color:black;></td>";
}
echo "</tr>";
@@ -526,14 +553,14 @@ if ($str3) {
<td align=center>勝</td>
</tr>
<?php
$prizeColumn = "{$rankColumn}p";
$gameColumn = "{$rankColumn}g";
$winColumn = "{$rankColumn}w";
$drawColumn = "{$rankColumn}d";
$loseColumn = "{$rankColumn}l";
$prizeColumn = RankColumn::from("{$rankColumn}p");
$gameColumn = RankColumn::from("{$rankColumn}g");
$winColumn = RankColumn::from("{$rankColumn}w");
$drawColumn = RankColumn::from("{$rankColumn}d");
$loseColumn = RankColumn::from("{$rankColumn}l");
$tournamentRankerList = General::createGeneralObjListFromDB(
$db->queryFirstColumn('SELECT general_id FROM rank_data WHERE `type`= %s ORDER BY value DESC LIMIT 40', $gameColumn),
[$prizeColumn, $gameColumn, $winColumn, $drawColumn, $loseColumn, 'leadership', 'strength', 'intel', 'no', 'npc', 'name'],
$db->queryFirstColumn('SELECT general_id FROM rank_data WHERE `type`= %s ORDER BY value DESC LIMIT 40', $gameColumn->value),
[$prizeColumn->value, $gameColumn->value, $winColumn->value, $drawColumn->value, $loseColumn->value, 'leadership', 'strength', 'intel', 'no', 'npc', 'name'],
0
);
usort($tournamentRankerList, function (General $lhs, General $rhs) use ($gameColumn, $winColumn, $drawColumn, $loseColumn) {
+2 -1
View File
@@ -337,6 +337,7 @@ $templates = new \League\Plates\Engine('templates');
'ourGeneral' => $ourGeneral,
'iconPath' => GetImageURL($general['imgsvr']) . '/' . $general['picture'],
'isNPC' => $isNPC,
'npc' => $general['npc'],
'wounded' => $wounded,
'name' => $name,
'nameText' => $nameText,
@@ -364,7 +365,7 @@ $templates = new \League\Plates\Engine('templates');
}
$generalsName = array_map(function ($gen) {
return getColoredName($gen['name'], $gen['npc']);
return formatName($gen['name'], $gen['npc']);
}, $generals);
$enemyCrew = 0;
-269
View File
@@ -1,269 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("내무부", 1);
$me = $db->queryFirstRow('SELECT no, nation, officer_level, con, turntime, belong, permission, penalty FROM general WHERE owner=%i', $userID);
$nationID = $me['nation'];
$nation = $db->queryFirstRow('SELECT nation,level,name,color,type,gold,rice,bill,rate,scout,war,secretlimit,capital FROM nation WHERE nation = %i', $nationID);
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
$permission = checkSecretPermission($me);
if ($permission < 0) {
echo '국가에 소속되어있지 않습니다.';
die();
} else if ($permission < 1) {
echo "권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.";
die();
}
if ($me['officer_level'] >= 5) {
$btn = "submit";
$read = "";
} else {
$btn = "hidden";
$read = "readonly";
}
$nationStor->cacheValues(['notice', 'scout_msg', 'available_war_setting_cnt']);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 내무부</title>
<?= WebUtil::printStaticValues([
'editable' => ($me['officer_level'] >= 5 || $permission == 4),
'nationMsg' => $nationStor->notice ?? '',
'scoutMsg' => $nationStor->scout_msg ?? '',
]) ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('vue', 'v_dipcenter', true) ?>
</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 colspan=9 align=center bgcolor=blue>외 교 관 계</td>
</tr>
<tr>
<td width=130 align=center class=bg1>국 가 명</td>
<td width=50 align=center class=bg1>국력</td>
<td width=40 align=center class=bg1>장수</td>
<td width=40 align=center class=bg1>속령</td>
<td width=80 align=center class=bg1>상태</td>
<td width=60 align=center class=bg1>기간</td>
<td width=100 align=center class=bg1>종 료 시 점</td>
</tr>
<?php
$admin = $gameStor->getValues(['year', 'month']);
$cityCntList = Util::convertPairArrayToDict($db->queryAllLists('SELECT nation, count(city) FROM city GROUP BY nation'));
$dipStateList = Util::convertArrayToDict($db->query('SELECT you,state,term FROM diplomacy WHERE me = %i', $nationID), 'you');
$nationsList = getAllNationStaticInfo();
uasort($nationsList, function (array $lhs, array $rhs) {
return - ($lhs['power'] <=> $rhs['power']);
});
foreach ($nationsList as $staticNation) :
//속령수
$staticNationID = $staticNation['nation'];
$cityCnt = $cityCntList[$staticNation['nation']] ?? 0;
$dipStateText = '-';
$dipTermText = '-';
$dipEndDateText = '-';
if ($staticNationID !== $nationID) {
$diplomacyState = $dipStateList[$staticNationID];
$dipStateText = [
0 => "<font color=red>교 전</font>",
1 => "<font color=magenta>선포중</font>",
2 => "통 상",
7 => "<font color=green>불가침</font>",
][$diplomacyState['state']];
if ($diplomacyState['term']) {
$dipEndMonth = $admin['month'] + $diplomacyState['term'] - 1;
$dipEndYear = $admin['year'] + intdiv($dipEndMonth, 12);
$dipEndMonth = $dipEndMonth % 12 + 1;
$dipTermText = $diplomacyState['term'] . '개월';
$dipEndDateText = "{$dipEndYear}年 {$dipEndMonth}月";
}
}
?>
<tr>
<td class='center' style='color:<?= newColor($staticNation['color']) ?>;background-color:<?= $staticNation['color'] ?>'><?= $staticNation['name'] ?></td>
<td class='center'><?= $staticNation['power'] ?></td>
<td class='center'><?= $staticNation['gennum'] ?></td>
<td class='center'><?= $cityCnt ?></td>
<td class='center'><?= $dipStateText ?></td>
<td class='center'><?= $dipTermText ?></td>
<td class='center'><?= $dipEndDateText ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php
// 수입 연산
$cityList = $db->query('SELECT * FROM city WHERE nation=%i', $nationID);
$dedicationList = $db->query('SELECT dedication FROM general WHERE nation=%i AND npc!=5', $nationID);
$goldIncome = getGoldIncome($nation['nation'], $nation['level'], $nation['rate'], $nation['capital'], $nation['type'], $cityList);
$warIncome = getWarGoldIncome($nation['type'], $cityList);
$totalGoldIncome = $goldIncome + $warIncome;
$riceIncome = getRiceIncome($nation['nation'], $nation['level'], $nation['rate'], $nation['capital'], $nation['type'], $cityList);
$wallIncome = getWallIncome($nation['nation'], $nation['level'], $nation['rate'], $nation['capital'], $nation['type'], $cityList);
$totalRiceIncome = $riceIncome + $wallIncome;
$outcome = getOutcome($nation['bill'], $dedicationList);
$budgetgold = $nation['gold'] + $totalGoldIncome - $outcome;
$budgetrice = $nation['rice'] + $totalRiceIncome - $outcome;
$budgetgolddiff = $totalGoldIncome - $outcome;
$budgetricediff = $totalRiceIncome - $outcome;
if ($budgetgolddiff > 0) {
$budgetgolddiff = '+' . number_format($budgetgolddiff);
} else {
$budgetgolddiff = number_format($budgetgolddiff);
}
if ($budgetricediff > 0) {
$budgetricediff = '+' . number_format($budgetricediff);
} else {
$budgetricediff = number_format($budgetricediff);
}
?>
<div class='tb_layout bg0' style='margin:auto;width: 1000px;' id="editorForm">
</div>
<table class="tb_layout bg0" style="margin:auto;">
<form name=form1 method=post action=c_dipcenter.php>
<tr>
<td colspan=2 align=center bgcolor=green>예 산 &amp; 정 책</td>
</tr>
<tr>
<td colspan=2>
<table width=998 class='tb_layout bg0'>
<tr>
<td colspan=2 align=center class=bg1>자금 예산</td>
<td colspan=2 align=center class=bg1>병량 예산</td>
</tr>
<tr>
<td width=248 align=right class=bg1>현 재&nbsp;&nbsp;&nbsp;</td>
<td width=248 align=center><?= number_format($nation['gold']) ?></td>
<td width=248 align=right class=bg1>현 재&nbsp;&nbsp;&nbsp;</td>
<td width=248 align=center><?= number_format($nation['rice']) ?></td>
</tr>
<tr>
<td align=right class=bg1>단기수입&nbsp;&nbsp;&nbsp;</td>
<td align=center>+<?= number_format($warIncome) ?></td>
<td align=right class=bg1>둔전수입&nbsp;&nbsp;&nbsp;</td>
<td align=center>+<?= number_format($wallIncome) ?></td>
</tr>
<tr>
<td align=right class=bg1>세 금&nbsp;&nbsp;&nbsp;</td>
<td align=center>+<?= number_format($goldIncome) ?></td>
<td align=right class=bg1>세 곡&nbsp;&nbsp;&nbsp;</td>
<td align=center>+<?= number_format($riceIncome) ?></td>
</tr>
<tr>
<td align=right class=bg1>수입 / 지출&nbsp;&nbsp;&nbsp;</td>
<td align=center>+<?= number_format($totalGoldIncome) ?> / -<?= number_format($outcome) ?></td>
<td align=right class=bg1>수입 / 지출&nbsp;&nbsp;&nbsp;</td>
<td align=center>+<?= number_format($totalRiceIncome) ?> / -<?= number_format($outcome) ?></td>
</tr>
<tr>
<td align=right class=bg1>국고 예산&nbsp;&nbsp;&nbsp;</td>
<td align=center><?= number_format($budgetgold) ?> (<?= $budgetgolddiff ?>)</td>
<td align=right class=bg1>병량 예산&nbsp;&nbsp;&nbsp;</td>
<td align=center><?= number_format($budgetrice) ?> (<?= $budgetricediff ?>)</td>
</tr>
<tr>
<td align=right class=bg1>세율 (5 ~ 30%)&nbsp;&nbsp;&nbsp;</td>
<td align=center><input type=text <?= $read ?> name=rate style=text-align:right;color:white;background-color:black; size=3 maxlength=3 value=<?= $nation['rate'] ?>>% <input type=<?= $btn ?> name=btn value=세율></td>
<td align=right class=bg1>봉급 지급률 (20 ~ 200%)&nbsp;&nbsp;&nbsp;</td>
<td align=center><input type=text <?= $read ?> name=bill style=text-align:right;color:white;background-color:black; size=3 maxlength=3 value=<?= $nation['bill'] ?>>% <input type=<?= $btn ?> name=btn value=지급률></td>
</tr>
<tr>
<td align=right class=bg1>기밀 권한 (1 ~ 99년)&nbsp;&nbsp;&nbsp;</td>
<td align=center><input type=text <?= $read ?> name=secretlimit style=text-align:right;color:white;background-color:black; size=3 maxlength=3 value=<?= $nation['secretlimit'] ?>>년 <input type=<?= $btn ?> name=btn value=기밀권한></td>
<td align=right class=bg1>전쟁 허용/금지 변경 가능</td>
<td align=center><?= $nationStor->getValue('available_war_setting_cnt') ?>회(월 +<?= GameConst::$incAvailableWarSettingCnt ?>회, 최대<?= GameConst::$maxAvailableWarSettingCnt ?>회)</td>
</tr>
<tr>
<td colspan=4 align=center>
<?php
if ($nation['scout'] == 0) {
echo "
<input type=$btn name=btn value='임관 금지'>";
} else {
echo "
<input type=$btn name=btn value='임관 허가'>";
}
if ($nation['war'] == 0) {
echo "
<input type=$btn name=btn value='전쟁 금지'>";
} else {
echo "
<input type=$btn name=btn value='전쟁 허가'>";
}
?>
</td>
</tr>
</table>
<tr>
<td colspan=2>기밀 권한이란, 암행부를 열람할 수 있는 일반 장수의 최소 사관 년수를 의미합니다.</td>
</tr>
<tr>
<td colspan=2 height=10></td>
</tr>
</form>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td><?= backButton() ?></td>
</tr>
<tr>
<td><?= banner() ?></td>
</tr>
</table>
</body>
</html>
-236
View File
@@ -1,236 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("중원정보", 1);
$mapTheme = $gameStor->map_theme ?? 'che';
$me = $db->queryFirstRow('SELECT no,nation FROM general WHERE owner=%i', $userID);
$myNationID = $me['nation'];
$nations = array_filter(getAllNationStaticInfo(), function (array $nation) {
return $nation['level'];
});
uasort($nations, function (array $lhs, array $rhs) {
return - ($lhs['power'] <=> $rhs['power']);
});
$nationCnt = count($nations);
foreach ($db->queryAllLists('SELECT nation, count(city) FROM city WHERE nation != 0 GROUP BY nation') as [$nationID, $cityCnt]) {
$nations[$nationID]['city_cnt'] = $cityCnt;
}
$realConflict = [];
foreach ($db->queryAllLists('SELECT city, `name`, conflict FROM city WHERE conflict!=%s', '{}') as [
$cityID,
$cityName,
$rawConflict
]) {
$rawConflict = Json::decode($rawConflict);
if (count($rawConflict) < 2) {
continue;
}
$sum = array_sum($rawConflict);
$conflict = [];
foreach ($rawConflict as $nationID => $killnum) {
$conflict[$nationID] = [
'killnum' => $killnum,
'percent' => round(100 * $killnum / $sum, 1),
'name' => $nations[$nationID]['name'],
'color' => $nations[$nationID]['color']
];
}
$realConflict[] = [$cityID, $cityName, $conflict];
};
$diplomacyList = [];
foreach ($db->queryAllLists('SELECT me, you, state FROM diplomacy') as [$me, $you, $state]) {
if (!key_exists($me, $diplomacyList)) {
$diplomacyList[$me] = [];
}
$diplomacyList[$me][$you] = $state;
}
$cellWidth = intdiv(888, max(1, $nationCnt));
$defaultStateChar = '?';
$sameNationStateChar = '';
$infomativeStateCharMap = [
0 => '<span style="color:red;">★</span>',
1 => '<span style="color:magenta;">▲</span>',
2 => 'ㆍ',
7 => '<span style="color:green;">@</span>'
];
$neutralStateCharMap = [
0 => '<span style="color:red;">★</span>',
1 => '<span style="color:magenta;">▲</span>'
];
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 중원 정보</title>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('d_shared/base_map.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/map.css') ?>
<?= WebUtil::printCSS('css/history.css') ?>
<?= WebUtil::printDist('ts', ['common', 'map']) ?>
<script>
window.serverNick = '<?= DB::prefix() ?>';
window.serverID = '<?= UniqueConst::$serverID ?>';
$(function() {
reloadWorldMap({
neutralView: true,
showMe: true,
useCachedMap: true
});
});
</script>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td>중 원 정 보<br><?= backButton() ?></td>
</tr>
</table>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td colspan=<?= $nationCnt + 1 ?> align=center bgcolor=blue>외 교 현 황</td>
</tr>
<tr>
<td align=center width=130 style=background-color:<?= GameConst::$basecolor2 ?>;>&nbsp;</td>
<?php foreach ($nations as $nation) : ?>
<td align=center width=<?= $cellWidth ?> style='background-color:<?= $nation['color'] ?>;color:<?= newColor($nation['color']) ?>'><?= $nation['name'] ?></td>
<?php endforeach; ?>
</tr>
<?php foreach ($nations as $me => $meNation) : ?>
<tr style='text-align:center;'>
<td align=center style='background-color:<?= $meNation['color'] ?>;color:<?= newColor($meNation['color']) ?>'><?= $meNation['name'] ?></td>
<?php foreach (array_keys($nations) as $you) : ?>
<td <?= ($me == $myNationID || $you == $myNationID) ? 'style="background-color:' . GameConst::$basecolor3 . '"' : '' ?>><?php
if ($me == $you) {
echo $sameNationStateChar;
} else if ($me == $myNationID || $you == $myNationID || $session->userGrade >= 5) {
echo $infomativeStateCharMap[$diplomacyList[$me][$you]] ?? $defaultStateChar;
} else {
echo $neutralStateCharMap[$diplomacyList[$me][$you]] ?? $defaultStateChar;
}
?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
<tr>
<td colspan=<?= $nationCnt + 1 ?> align=center>불가침 : <font color=limegreen>@</font>, 통상 : ㆍ, 선포 : <font color=magenta>▲</font>, 교전 : <font color=red>★</font>
</td>
</tr>
</table>
<?php if ($realConflict) : ?>
<br>
<table align='center' width=1000 class='tb_layout bg0'>
<tr>
<td colspan=2 align=center bgcolor=magenta>분 쟁 현 황</td>
</tr>
<?php foreach ($realConflict as list($cityID, $cityName, $conflict)) : ?>
<tr>
<td align=center width=48><?= $cityName ?></td>
<td style='width:948px;position:relative;'>
<table class='tb_layout bg0' style='width:100%;'>
<?php foreach ($conflict as $item) : ?>
<tr>
<td width=130 align=right style='color:<?= newColor($item['color']) ?>;background-color:<?= $item['color'] ?>;'><?= $item['name'] ?>&nbsp;</td>
<td width=48 align=right><?= (float)$item['percent'] ?> %&nbsp;</td>
<td width=*>
<div style='display:inline-block;width:<?= $item['percent'] ?>%;background-color:<?= $item['color'] ?>;'>&nbsp;</div>
</td>
</tr>
<?php endforeach; ?>
</table>
</td>
</tr>
<?php endforeach; ?>
<tr>
<td colspan=2 height=5 class='bg1'></td>
</tr>
</table>
<?php endif; ?>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td colspan=5 align=center bgcolor=green>
<font size=3>중 원 지 도</font>
</td>
</tr>
<tr>
<td width=698 height=420>
<?= getMapHtml($mapTheme) ?>
</td>
<td id='nation_list_frame'>
<table id='nation_list'>
<thead>
<tr>
<th width=130>국명</th>
<th width=70>국력</th>
<th width=45>장수</th>
<th width=45>속령</th>
</tr>
</thead>
<tbody>
<?php foreach ($nations as $nation) : ?>
<tr>
<td><span style='color:<?= newColor($nation['color']) ?>;background-color:<?= $nation['color'] ?>'><?= $nation['name'] ?></td>
<td style='text-align:right'><?= number_format($nation['power']) ?></td>
<td style='text-align:right'><?= number_format($nation['gennum']) ?></td>
<td style='text-align:right'><?= number_format($nation['city_cnt']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot></tfoot>
</table>
</td>
</tr>
</table>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td><?= backButton() ?></td>
</tr>
<tr>
<td><?= banner() ?></td>
</tr>
</table>
</body>
</html>
+1 -1
View File
@@ -172,7 +172,7 @@ $templates = new \League\Plates\Engine('templates');
$general['expLevelText'] = getExpLevel($general['experience']);
$general['nameText'] = getColoredName($general['name'], $general['npc']);
$general['nameText'] = formatName($general['name'], $general['npc']);
$general['modeText'] = formatDefenceTrain($general['defence_train']);
$general['crewtypeText'] = GameUnitConst::byId($general['crewtype'])->name ?? '-';
+72 -58
View File
@@ -71,7 +71,8 @@ $sel = [$type => "selected"];
</table>
<?php
$nation = getNationStaticInfo($me['nation']); //국가정보
$nation = $db->queryFirstRow('SELECT nation, name, color, type, level, capital, gennum, `power`, `rate` from nation WHERE nation = %i', $nationID); //국가정보
$nationTypeObj = buildNationTypeClass($nation['type']);
$officerList = [];
foreach ($db->query('SELECT no,name,npc,city,officer_level,officer_city,belong FROM general WHERE nation = %i AND 2 <= officer_level AND officer_level <= 4', $nationID) as $officer) {
@@ -82,6 +83,17 @@ $sel = [$type => "selected"];
$officerList[$officerCityID][$officer['officer_level']] = $officer;
}
$generalList = $db->query('SELECT npc, name, city FROM general WHERE nation = %i', $me['nation']);
$cityGeneralList = [];
foreach ($generalList as $general) {
$cityID = $general['city'];
if (!key_exists($cityID, $cityGeneralList)) {
$cityGeneralList[$cityID] = [];
}
$cityGeneralList[$cityID][] = formatName($general['name'], $general['npc']);
}
$cityList = $db->query('SELECT *,pop/pop_max as poprate from city where nation=%i', $nationID);
@@ -171,8 +183,12 @@ $sel = [$type => "selected"];
];
$cityOfficerList = $officerList[$cityID] ?? [];
$effectiveOfficerCnt = 0;
foreach ($cityOfficerList as $cityOfficer) {
$officerName[$cityOfficer['officer_level']] = getColoredName($cityOfficer['name'], $cityOfficer['npc']);
if ($cityOfficer['city'] == $cityID) {
$effectiveOfficerCnt += 1;
}
$officerName[$cityOfficer['officer_level']] = formatName($cityOfficer['name'], $cityOfficer['npc']);
}
if ($type == 10 && $city['region'] != $region) {
@@ -187,62 +203,60 @@ $sel = [$type => "selected"];
$city['trade'] = "- ";
}
echo "
<table align=center width=1000 class='tb_layout bg2'>
<tr>
<td colspan=12 style=color:" . newColor($nation['color']) . "; bgcolor={$nation['color']}><font size=2>【 " . CityConst::$regionMap[$city['region']] . " | " . CityConst::$levelMap[$city['level']] . " 】 {$city['name']}</font></td>
</tr>
<tr>
<td align=center width=46 class='bg1'>주민</td>
<td align=center width=140>{$city['pop']}/{$city['pop_max']}</td>
<td align=center width=46 class='bg1'>농업</td>
<td align=center width=140>{$city['agri']}/{$city['agri_max']}</td>
<td align=center width=46 class='bg1'>상업</td>
<td align=center width=140>{$city['comm']}/{$city['comm_max']}</td>
<td align=center width=46 class='bg1'>치안</td>
<td align=center width=140>{$city['secu']}/{$city['secu_max']}</td>
<td align=center width=46 class='bg1'>수비</td>
<td align=center width=140>{$city['def']}/{$city['def_max']}</td>
<td align=center width=46 class='bg1'>성벽</td>
<td align=center width=140>{$city['wall']}/{$city['wall_max']}</td>
</tr>
<tr>
<td align=center class='bg1'>민심</td>
<td align=center>" . round($city['trust'], 1) . "</td>
<td align=center class='bg1'>시세</td>
<td align=center>{$city['trade']}%</td>
<td align=center class='bg1'>인구</td>
<td align=center>" . round($city['pop'] / $city['pop_max'] * 100, 2) . " %</td>
<td align=center class='bg1'>태수</td>
<td align=center>";
echo $officerName[4];
echo "</td>
<td align=center class='bg1'>군사</td>
<td align=center>";
echo $officerName[3];
echo "</td>
<td align=center class='bg1'>종사</td>
<td align=center>";
echo $officerName[2];
echo "</td>
</tr>
<tr>
<td align=center class='bg1'>장수</td>
<td colspan=11>";
$generalList = $db->query('SELECT npc, name FROM general WHERE city = %i AND nation = %i', $city['city'], $me['nation']);
if (!$generalList) {
echo "-";
}
foreach ($generalList as $general) {
echo getColoredName($general['name'], $general['npc']) . ', ';
}
echo "
</td>
</tr>
</table>
";
}
$cityGoldIncome = $nation['rate'] / 20 * calcCityGoldIncome($city, $effectiveOfficerCnt, $nation['capital'] == $cityID, $nation['level'], $nationTypeObj);
$cityRiceIncome = $nation['rate'] / 20 * calcCityRiceIncome($city, $effectiveOfficerCnt, $nation['capital'] == $cityID, $nation['level'], $nationTypeObj);
$cityWallIncome = $nation['rate'] / 20 * calcCityWallRiceIncome($city, $effectiveOfficerCnt, $nation['capital'] == $cityID, $nation['level'], $nationTypeObj);
?>
<table align=center width=1000 class='tb_layout bg2'>
<tr>
<td colspan=10 style="color:<?= newColor($nation['color']) ?>; background-color:<?= $nation['color'] ?>;">
<font size=2>【 <?= CityConst::$regionMap[$city['region']] ?> | <?= CityConst::$levelMap[$city['level']] ?> 】 <?= $city['name'] ?></font>
</td>
</tr>
<tr style='text-align:center;'>
<td width=60 class='bg1'>주민</td>
<td width=140 class='pop-value'><?= $city['pop'] ?>/<?= $city['pop_max'] ?></td>
<td width=60 class='bg1'>인구율</td>
<td width=140 class='pop-prop-value'><?= round($city['pop'] / $city['pop_max'] * 100, 2) ?>%</td>
<td width=60 class='bg1'>자금 수입</td>
<td width=140 class='gold-income'><?= number_format($cityGoldIncome) ?></td>
<td width=60 class='bg1'>군량 수입</td>
<td width=140 class='rice-income'><?= number_format($cityRiceIncome) ?></td>
<td width=60 class='bg1'>둔전 수입</td>
<td width=140 class='wall-income'><?= number_format($cityWallIncome) ?></td>
</tr>
<tr style='text-align:center;'>
<td class='bg1'>농업</td>
<td class='agri-value'><?= $city['agri'] ?>/<?= $city['agri_max'] ?></td>
<td class='bg1'>상업</td>
<td class='comm-value'><?= $city['comm'] ?>/<?= $city['comm_max'] ?></td>
<td class='bg1'>치안</td>
<td class='secu-value'><?= $city['secu'] ?>/<?= $city['secu_max'] ?></td>
<td class='bg1'>수비</td>
<td class='def-value'><?= $city['def'] ?>/<?= $city['def_max'] ?></td>
<td class='bg1'>성벽</td>
<td class='wall-value'><?= $city['wall'] ?>/<?= $city['wall_max'] ?></td>
</tr>
<tr style='text-align:center;'>
<td class='bg1'>민심</td>
<td class='trust-value'><?= round($city['trust'], 1) ?></td>
<td class='bg1'>시세</td>
<td class='trade-value'><?= $city['trade'] ?>%</td>
<td class='bg1'>태수</td>
<td class='officer-4-value'><?= $officerName[4] ?></td>
<td class='bg1'>군사</td>
<td class='officer-3-value'><?= $officerName[3] ?></td>
<td class='bg1'>종사</td>
<td class='officer-2-value'><?= $officerName[2] ?></td>
</tr>
<tr>
<td style='text-align:center;' class='bg1'>장수</td>
<td colspan=9 class='city-generals'><?= key_exists($cityID, $cityGeneralList) ? join(', ', $cityGeneralList[$cityID]) : '-' ?></td>
</tr>
</table>
<?php } ?>
<table align=center width=1000 class='tb_layout bg0 anchor'>
<tr>
@@ -252,7 +266,7 @@ $sel = [$type => "selected"];
<td><?= banner() ?></td>
</tr>
</table>
<div id="helper_genlist" style="display:none;"></div>
</body>
<div id="helper_genlist" style="display:none;"></div>
</html>
+1 -7
View File
@@ -146,13 +146,7 @@ if ($gameStor->isunited) {
$intel = "{$general['intel']}";
}
if ($general['npc'] >= 2) {
$name = "<font color=cyan>{$general['name']}</font>";
} elseif ($general['npc'] == 1) {
$name = "<font color=skyblue>{$general['name']}</font>";
} else {
$name = "{$general['name']}";
}
$name = formatName($general['name'], $general['npc']);
if (key_exists($general['owner'], $ownerNameList)) {
$name = $name . '<br><small>(' . $ownerNameList[$general['owner']] . ')</small>';
+28 -5
View File
@@ -50,9 +50,18 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 내정보</title>
<script>
var availableDieImmediately = <?= $availableDieImmediately ? 'true' : 'false' ?>;
</script>
<?= WebUtil::printStaticValues([
'availableDieImmediately' => $availableDieImmediately,
'staticValues' => [
'items' => Util::mapWithKey(fn (string $key, BaseItem $item) => [
'name' => $item->getName(),
'rawName' => $item->getRawName(),
'className' => $item->getRawClassName(),
'cost' => $item->getCost(),
'isBuyable' => $item->isBuyable(),
], $me->getItems())
]
]) ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
@@ -72,8 +81,8 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
</div>
<div class="col col-12 col-md-6">
<div class="row">
<div class="col" style='padding-left:4ch;'>
<div class="row mx-0 gx-0">
<div class="col" style='padding-left:2ch;'>
토너먼트 【
<input type=radio class='tnmt' name=tnmt value=0 <?= $me->getVar('tnmt') == 0 ? "checked" : ""; ?>>수동참여
<input type=radio class='tnmt' name=tnmt value=1 <?= $me->getVar('tnmt') == 1 ? "checked" : ""; ?>>자동참여
@@ -94,6 +103,8 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<option value=0 <?= (!$use_auto_nation_turn) ? "selected" : ""; ?>>허용 안함</option>
</select>】<br>
∞<span style='color:orange'>수뇌가 되었을 때 휴식 턴이어도 적당한 턴을 알아서 넣는 것을 허용합니다.</span><br><br>
<?php else : ?>
<input type="hidden" id='use_auto_nation_turn' name='use_auto_nation_turn' value="1" />
<?php endif; ?>
수비 【<select id='defence_train' name='defence_train'>
<?php foreach ([90, 80, 60, 40] as $targetDefenceTrain) : ?>
@@ -136,6 +147,18 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
</div>
</div>
</div>
<div class="row">
<div class="col">아이템 파기</div>
</div>
<div class="row mx-1">
<div class="btn-group" role="group">
<?php foreach ($me->getItems() as $itemKey => $item) : ?>
<button type="button" data-item-type='<?=$itemKey?>' class="drop-item-btn btn btn-primary <?= $item->getName() == '-' ? 'disabled' : '' ?>"><?= $item->getName() ?></button>
<?php endforeach; ?>
</div>
</div>
<br>
개인용 CSS<br>
+79 -49
View File
@@ -15,6 +15,7 @@ increaseRefresh("토너먼트", 1);
TurnExecutionHelper::executeAllCommand();
$me = $db->queryFirstRow('select no,tournament,con,turntime from general where owner=%i', $userID);
$generalID = $session->generalID;
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_msg', 'tnmt_type', 'develcost', 'tnmt_trig']);
@@ -25,34 +26,76 @@ if ($con >= 2) {
}
switch ($admin['tnmt_type']) {
default:
throw new \RuntimeException('invalid tnmt_type');
case 0:
$tnmt_type = "<font color=cyan>전력전</font>";
case convertTournamentType('전력전'):
$tnmt_type = "전력전";
$color = 'cyan';
$tp = "total";
$tp2 = "종합";
$tp3 = "total";
break;
case 1:
$tnmt_type = "<font color=cyan>통솔전</font>";
case convertTournamentType('통솔전'):
$tnmt_type = "통솔전";
$color = 'cyan';
$tp = "leadership";
$tp2 = "통솔";
$tp3 = "leadership";
break;
case 2:
$tnmt_type = "<font color=cyan>일기토</font>";
case convertTournamentType('일기토'):
$tnmt_type = "일기토";
$color = 'cyan';
$tp = "strength";
$tp2 = "무력";
$tp3 = "strength";
break;
case 3:
$tnmt_type = "<font color=cyan>설전</font>";
case convertTournamentType('설전'):
$tnmt_type = "설전";
$color = 'cyan';
$tp = "intel";
$tp2 = "지력";
$tp3 = "intel";
break;
default:
throw new \RuntimeException('invalid tnmt_type');
}
$bettingID = $gameStor->last_tournament_betting_id ?? 0;
if ($bettingID != 0) {
$betting = $bettingID != 0 ? new Betting($bettingID) : null;
$info = $betting->getInfo();
} else {
$info = getDummyBettingInfo($tnmt_type);
}
$myBet = [];
$globalBet = [];
if ($bettingID != 0) {
$betting = $bettingID != 0 ? new Betting($bettingID) : null;
$info = $betting->getInfo();
foreach ($db->queryAllLists(
'SELECT general_id, user_id, amount, betting_type FROM ng_betting WHERE betting_id = %i',
$bettingID
) as [$betGeneralID, $userID, $amount, $bettingTypeKey]) {
$bettingKey = Json::decode($bettingTypeKey)[0];
if ($betGeneralID == $generalID) {
$myBet[$bettingKey] = $amount;
}
if (key_exists($bettingKey, $globalBet)) {
$globalBet[$bettingKey] += $amount;
} else {
$globalBet[$bettingKey] = $amount;
}
}
} else {
$info = getDummyBettingInfo($tnmt_type);
}
$myBetTotal = array_sum($myBet);
$globalBetTotal = array_sum($globalBet);
?>
<!DOCTYPE html>
<html>
@@ -198,7 +241,7 @@ switch ($admin['tnmt_type']) {
if ($str2) {
$str2 = ', ' . $str2;
}
$str3 = getTournamentTerm();
$str3 = getTournamentTermText();
if ($str3) {
$str3 = ', ' . $str3;
}
@@ -209,7 +252,7 @@ switch ($admin['tnmt_type']) {
</tr>
<tr>
<td colspan=8 align=center>
<font color=white size=6><?= $tnmt_type ?> (<?= $str1 . $str2 . $str3 ?>)</font>
<font color=white size=6><span style="color:<?= $color ?>"><?= $tnmt_type ?></span> (<?= $str1 . $str2 . $str3 ?>)</font>
</td>
</tr>
<tr>
@@ -240,11 +283,7 @@ switch ($admin['tnmt_type']) {
if ($general['name'] == "") {
$general['name'] = "-";
}
if ($general['npc'] >= 2) {
$general['name'] = "<font color=cyan>" . $general['name'] . "</font>";
} elseif ($general['npc'] == 1) {
$general['name'] = "<font color=skyblue>" . $general['name'] . "</font>";
}
$general['name'] = formatName($general['name'], $general['npc']);
echo "<td colspan=16>{$general['name']}</td>";
}
@@ -270,11 +309,7 @@ switch ($admin['tnmt_type']) {
if ($general['name'] == "") {
$general['name'] = "-";
}
if ($general['npc'] >= 2) {
$general['name'] = "<font color=cyan>" . $general['name'] . "</font>";
} elseif ($general['npc'] == 1) {
$general['name'] = "<font color=skyblue>" . $general['name'] . "</font>";
}
$general['name'] = formatName($general['name'], $general['npc']);
if ($general['win'] > 0) {
$line[$i] = "<font color=red>";
$cent[intdiv($i, 2)] = "<font color=red>";
@@ -316,11 +351,7 @@ switch ($admin['tnmt_type']) {
if ($general['name'] == "") {
$general['name'] = "-";
}
if ($general['npc'] >= 2) {
$general['name'] = "<font color=cyan>" . $general['name'] . "</font>";
} elseif ($general['npc'] == 1) {
$general['name'] = "<font color=skyblue>" . $general['name'] . "</font>";
}
$general['name'] = formatName($general['name'], $general['npc']);
if ($general['win'] > 0) {
$line[$i] = "<font color=red>";
$cent[intdiv($i, 2)] = "<font color=red>";
@@ -363,11 +394,7 @@ switch ($admin['tnmt_type']) {
if ($general['name'] == "") {
$general['name'] = "-";
}
if ($general['npc'] >= 2) {
$general['name'] = "<font color=cyan>" . $general['name'] . "</font>";
} elseif ($general['npc'] == 1) {
$general['name'] = "<font color=skyblue>" . $general['name'] . "</font>";
}
$general['name'] = formatName($general['name'], $general['npc']);
if ($general['win'] > 0) {
$line[$i] = "<font color=red>";
$cent[intdiv($i, 2)] = "<font color=red>";
@@ -409,11 +436,7 @@ switch ($admin['tnmt_type']) {
if ($general['name'] == "") {
$general['name'] = "-";
}
if ($general['npc'] >= 2) {
$general['name'] = "<font color=cyan>" . $general['name'] . "</font>";
} elseif ($general['npc'] == 1) {
$general['name'] = "<font color=skyblue>" . $general['name'] . "</font>";
}
$general['name'] = formatName($general['name'], $general['npc']);
if ($general['win'] > 0) {
$line[$i] = "<font color=red>";
$cent[intdiv($i, 2)] = "<font color=red>";
@@ -438,24 +461,31 @@ switch ($admin['tnmt_type']) {
echo "
</tr>";
$globalBet = $db->queryFirstList('SELECT * FROM betting WHERE general_id = 0') ?? [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,];
$globalBet = array_splice($globalBet, -16);
$globalBetTotal = array_sum($globalBet);
$admin = $gameStor->getValues(['tournament', 'phase']);
$bet = [];
for ($i = 0; $i < 16; $i++) {
if ($globalBet[$i] == 0) {
$bet[$i] = '∞';
continue;
$gold = [];
$keyMap = [];
foreach ($info->candidates as $key => $candidate) {
$keyMap[$candidate->aux['idx']] = $key;
}
foreach ($globalBet as $key => $amount) {
if ($amount == 0) {
$bet[$key] = "∞";
$gold[$key] = 0;
} else {
$rewardRatio = round($globalBetTotal / $amount, 2);
$bet[$key] = $rewardRatio;
$gold[$key] = $rewardRatio * ($myBet[$key] ?? 0);
}
$bet[$i] = round($globalBetTotal / $globalBet[$i], 2);
}
echo "
<tr align=center>";
for ($i = 0; $i < 16; $i++) {
echo "<td><font color=skyblue>{$bet[$i]}</font></td>";
foreach (range(0, 15) as $i) {
$amount = $bet[$keyMap[$i] ?? -1] ?? 0;
echo "<td><font color=skyblue>{$amount}</font></td>";
}
echo "
@@ -489,7 +519,7 @@ switch ($admin['tnmt_type']) {
printRow($k, $general['npc'], $general['name'], $general[$tp], $general['game'], $general['win'], $general['draw'], $general['lose'], $general['gd'], $general['gl'], $general['prmt']);
}
foreach (Util::range(count($generalList), 4) as $idx) {
printRow($idx, '', '', '', '', '', '', '', '', '', '');
printRow($idx, 0, '', '', '', '', '', '', '', '', '');
}
echo "
</table>
@@ -516,7 +546,7 @@ switch ($admin['tnmt_type']) {
printRow($k, $general['npc'], $general['name'], $general[$tp], $general['game'], $general['win'], $general['draw'], $general['lose'], $general['gd'], $general['gl'], $general['prmt']);
}
foreach (Util::range(count($generalList), 8) as $idx) {
printRow($idx, '', '', '', '', '', '', '', '', '', '');
printRow($idx, 0, '', '', '', '', '', '', '', '', '');
}
echo "
</table>
-85
View File
@@ -1,85 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
// $btn, $msg, $scoutmsg, $rate, $bill, $secretlimit
$btn = Util::getPost('btn');
//$msg = Util::getPost('msg');
//$scoutmsg = Util::getPost('scoutMsg');
$rate = Util::getPost('rate', 'int');
$bill = Util::getPost('bill', 'int');
$secretlimit = Util::getPost('secretlimit', 'int');
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$me = $db->queryFirstRow('SELECT `no`,nation,`officer_level`,permission,penalty FROM general WHERE `owner`=%i', $userID);
//내가 수뇌부이어야함
$permission = checkSecretPermission($me);
if ($permission < 0) {
header('location:b_myBossInfo.php', true, 303);
exit();
} else if ($me['officer_level'] < 5 && $permission != 4) {
header('location:b_myBossInfo.php', true, 303);
exit();
}
$nationID = $me['nation'];
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
/*if ($btn == "국가방침 수정") {
$msg = mb_substr($msg, 0, 16384);
//$msg = StringUtil::
$nationStor->notice = WebUtil::htmlPurify($msg);
} elseif ($btn == "임관 권유문 수정") {
$scoutmsg = mb_substr($scoutmsg, 0, 1000);
$nationStor->scout_msg = WebUtil::htmlPurify($scoutmsg);
} else*/if ($btn == "세율") {
$rate = Util::valueFit($rate, 5, 30);
$db->update('nation', [
'rate' => $rate,
], 'nation=%i', $nationID);
} elseif ($btn == "지급률") {
$bill = Util::valueFit($bill, 20, 200);
$db->update('nation', [
'bill' => $bill
], 'nation=%i', $nationID);
} elseif ($btn == "기밀권한") {
$secretlimit = Util::valueFit($secretlimit, 1, 99);
$db->update('nation', [
'secretlimit' => $secretlimit
], 'nation=%i', $nationID);
} elseif ($btn == "임관 금지") {
$db->update('nation', [
'scout' => 1
], 'nation=%i', $nationID);
} elseif ($btn == "임관 허가") {
$db->update('nation', [
'scout' => 0
], 'nation=%i', $nationID);
} elseif ($btn == "전쟁 금지") {
$avilableCnt = $nationStor->getValue('available_war_setting_cnt') ?? 0;
if ($avilableCnt > 0) {
$db->update('nation', [
'war' => 1
], 'nation=%i', $nationID);
$nationStor->setValue('available_war_setting_cnt', $avilableCnt - 1);
}
} elseif ($btn == "전쟁 허가") {
$avilableCnt = $nationStor->getValue('available_war_setting_cnt') ?? 0;
if ($avilableCnt > 0) {
$db->update('nation', [
'war' => 0
], 'nation=%i', $nationID);
$nationStor->setValue('available_war_setting_cnt', $avilableCnt - 1);
}
}
header('location:b_dipcenter.php');
+14 -4
View File
@@ -15,7 +15,7 @@ $sel = Util::getPost('sel', 'int');
$trig = Util::getPost('trig', 'int');
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$session = Session::requireGameLogin();
$userID = Session::getUserID();
$db = DB::db();
@@ -24,7 +24,11 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['tournament','phase','tnmt_type','develcost']);
$me = $db->queryFirstRow('SELECT no,name,tournament from general where owner=%i',$userID);
if(!$me){
$session->logoutGame();
header('location:b_tournament.php');
exit(1);
}
switch($admin['tnmt_type']) {
case 0: $tp = "total"; $tp2 = "전력전"; $tp3 = "leadership+strength+intel"; break;
case 1: $tp = "leadership"; $tp2 = "통솔전"; $tp3 = "leadership"; break;
@@ -40,6 +44,10 @@ if($btn == '참가') {
}
$general = $db->queryFirstRow('SELECT no,name,npc,leadership,strength,intel,explevel,gold,horse,weapon,book FROM general WHERE `no`=%i', $me['no']);
if(!$general){
header('location:b_tournament.php');
exit(1);
}
//{$admin['develcost']}원 참가비
if($general['gold'] < $admin['develcost']) {
@@ -90,8 +98,8 @@ if($btn == '참가') {
], 'no=%i', $general['no']);
}
$grpCount = $db->queryFirstField('SELECT count(*) FROM tournament where grp<10 GROUP BY grp HAVING count(*)=8');
if($grpCount >= 8) {
$grpCount = $db->queryFirstColumn('SELECT count(grp) FROM tournament where grp<10 GROUP BY grp;');
if(min($grpCount) >= 8) {
$gameStor->tournament = 2;
$gameStor->phase = 0;
}
@@ -217,6 +225,8 @@ if($btn == "자동개최설정") {
finallyAll($admin['tnmt_type'], $admin['tournament'], $admin['phase']);
} elseif($btn == "배정") {
final16set();
$phase = 0;
startBetting($admin['tnmt_type'], 720);
} elseif($btn == "베팅마감") {
$dt = date("Y-m-d H:i:s", time() + 60);
$gameStor->tournament=7;
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 B

+4 -6
View File
@@ -1,5 +1,3 @@
@charset "UTF-8";
.world_map {
width: 700px;
background: black;
@@ -69,11 +67,11 @@
}
.map_body .map_toggle_cityname::after {
content: "끄기"
content: " 끄기"
}
.map_body .map_toggle_cityname.active::after {
content: "켜기"
content: " 켜기"
}
.map_body .map_toggle_single_tap {
@@ -81,11 +79,11 @@
}
.map_body .map_toggle_single_tap::after {
content: "끄기"
content: " 끄기"
}
.map_body .map_toggle_single_tap.active::after {
content: "켜기"
content: " 켜기"
}
.world_map .city_tooltip {
+16 -18
View File
@@ -1,18 +1,16 @@
<div class="buttonPlate">
<a href="a_status.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력도</button></a>
<a href="a_kingdomList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력일람</button></a>
<a href="a_genList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">장수일람</button></a>
<a href="a_bestGeneral.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명장일람</button></a>
<a href="a_history.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">연감</button></a>
<a href="a_hallOfFame.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명예의전당</button></a>
<a href="a_emperior.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">왕조일람</button></a>
<a href="a_traffic.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">접속량정보</button></a>
<a href="/bbs/board" target="_blank"><button type="button" class="toolbarButton2">삼모게시판</button></a>
<a href="/bbs/tip" target="_blank"><button type="button" class="toolbarButton">팁/강좌</button></a>
<a href="/bbs/news" target="_blank"><button type="button" class="toolbarButton">삼국 일보</button></a>
<a href="/bbs/history2" target="_blank"><button type="button" class="toolbarButton">개인 열전</button></a>
<a href="/bbs/history3" target="_blank"><button type="button" class="toolbarButton">국가 열전</button></a>
<a href="/bbs/patch" target="_blank"><button type="button" class="toolbarButton">패치 내역</button></a>
<a href="battle_simulator.php" target="_blank"><button type="button" class="toolbarButton">전투 시뮬레이터</button></a>
<a href="<?=$site?>" target="_blank" class="open-window"><button type="button" class="toolbarButton"><?=$call?></button></a>
</div>
<?=$btnBegin??''?><a href="v_nationBetting.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">천통국 베팅</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="a_kingdomList.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">세력일람</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="a_genList.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">장수일람</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="a_bestGeneral.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">명장일람</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="a_history.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">연감</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="a_hallOfFame.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">명예의전당</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="a_emperior.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">왕조일람</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="a_traffic.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">접속량정보</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="/bbs/board" target="_blank" class="toolbarButton2 <?=$btnClass??""?>">삼모게시판</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="/bbs/tip" target="_blank" class="toolbarButton <?=$btnClass??""?>">팁/강좌</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="/bbs/news" target="_blank" class="toolbarButton <?=$btnClass??""?>">삼국 일보</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="/bbs/history2" target="_blank" class="toolbarButton <?=$btnClass??""?>">개인 열전</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="/bbs/history3" target="_blank" class="toolbarButton <?=$btnClass??""?>">국가 열전</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="/bbs/patch" target="_blank" class="toolbarButton <?=$btnClass??""?>">패치 내역</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="battle_simulator.php" target="_blank" class="toolbarButton <?=$btnClass??""?>">전투 시뮬레이터</a><?=$btnEnd??''?>
<?=$btnBegin??''?><a href="<?= $site ?>" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>"><?= $call ?></a><?=$btnEnd??''?>
+76 -52
View File
@@ -3,6 +3,8 @@
namespace sammo;
use DateTime;
use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn;
use sammo\Event\Action;
require_once 'process_war.php';
@@ -171,7 +173,7 @@ function cityInfo(General $generalObj)
];
foreach ($db->query('SELECT `officer_level`, `name`, npc, no FROM general WHERE officer_city = %i', $cityID) as $officer) {
$officerName[$officer['officer_level']] = getColoredName($officer['name'], $officer['npc']);
$officerName[$officer['officer_level']] = formatName($officer['name'], $officer['npc']);
}
$city['officerName'] = $officerName;
@@ -199,8 +201,8 @@ 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) ? formatName($topChiefs[12]['name'], $topChiefs[12]['npc']) : '-';
$level11Name = key_exists(11, $topChiefs) ? formatName($topChiefs[11]['name'], $topChiefs[11]['npc']) : '-';
$impossibleStrategicCommandLists = [];
$strategicCommandLists = GameConst::$availableChiefCommand['전략'];
@@ -472,7 +474,8 @@ function getCommandTable(General $general)
return $result;
}
function getChiefCommandTable(General $general){
function getChiefCommandTable(General $general)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->turnOnCache();
@@ -756,8 +759,8 @@ function generalInfo2(General $generalObj)
{
$general = $generalObj->getRaw();
$winRate = round($generalObj->getRankVar('killnum') / max($generalObj->getRankVar('warnum'), 1) * 100, 2);
$killRate = round($generalObj->getRankVar('killcrew') / max($generalObj->getRankVar('deathcrew'), 1) * 100, 2);
$winRate = round($generalObj->getRankVar(RankColumn::killnum) / max($generalObj->getRankVar(RankColumn::warnum), 1) * 100, 2);
$killRate = round($generalObj->getRankVar(RankColumn::killcrew) / max($generalObj->getRankVar(RankColumn::deathcrew), 1) * 100, 2);
$experienceBonus = $generalObj->onCalcStat($generalObj, 'experience', 10000) - 10000;
if ($experienceBonus > 0) {
@@ -821,9 +824,9 @@ function generalInfo2(General $generalObj)
</tr>
<tr>
<td width=64 style='text-align:center;' class='bg1'><b>전투</b></td>
<td width=132 style='text-align:center;'>{$generalObj->getRankVar('warnum')}</td>
<td width=132 style='text-align:center;'>{$generalObj->getRankVar(RankColumn::warnum)}</td>
<td width=48 style='text-align:center;' class='bg1'><b>계략</b></td>
<td width=98 style='text-align:center;'>{$generalObj->getRankVar('firenum')}</td>
<td width=98 style='text-align:center;'>{$generalObj->getRankVar(RankColumn::firenum)}</td>
<td width=48 style='text-align:center;' class='bg1'><b>사관</b></td>
<td width=98 style='text-align:center;'>{$general['belong']}년</td>
</tr>
@@ -831,17 +834,17 @@ function generalInfo2(General $generalObj)
<td style='text-align:center;' class='bg1'><b>승률</b></td>
<td style='text-align:center;'>{$winRate} %</td>
<td style='text-align:center;' class='bg1'><b>승리</b></td>
<td style='text-align:center;'>{$generalObj->getRankVar('killnum')}</td>
<td style='text-align:center;'>{$generalObj->getRankVar(RankColumn::killnum)}</td>
<td style='text-align:center;' class='bg1'><b>패배</b></td>
<td style='text-align:center;'>{$generalObj->getRankVar('deathnum')}</td>
<td style='text-align:center;'>{$generalObj->getRankVar(RankColumn::deathnum)}</td>
</tr>
<tr>
<td style='text-align:center;' class='bg1'><b>살상률</b></td>
<td style='text-align:center;'>{$killRate} %</td>
<td style='text-align:center;' class='bg1'><b>사살</b></td>
<td style='text-align:center;'>{$generalObj->getRankVar('killcrew')}</td>
<td style='text-align:center;'>{$generalObj->getRankVar(RankColumn::killcrew)}</td>
<td style='text-align:center;' class='bg1'><b>피살</b></td>
<td style='text-align:center;'>{$generalObj->getRankVar('deathcrew')}</td>
<td style='text-align:center;'>{$generalObj->getRankVar(RankColumn::deathcrew)}</td>
</tr>
</table>
<table width=498 class='tb_layout bg2 f_tnum'>
@@ -879,9 +882,9 @@ function generalInfo2(General $generalObj)
</table>";
}
function getOnlineNum()
function getOnlineNum(): int
{
return KVStorage::getStorage(DB::db(), 'game_env')->online;
return KVStorage::getStorage(DB::db(), 'game_env')->getValue('online') ?? 0;
}
function onlinegen(General $general)
@@ -1072,6 +1075,7 @@ function updateTraffic()
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxonline', 'maxrefresh']);
/** @var array{year:int,month:int,refresh:int,maxonline:int,maxrefresh:int} $admin */
//최다갱신자
$user = $db->queryFirstRow('select name,refresh from general order by refresh desc limit 1');
@@ -1121,7 +1125,7 @@ function CheckOverhead()
function isLock()
{
return DB::db()->queryFirstField("SELECT plock from plock limit 1") != 0;
return DB::db()->queryFirstField("SELECT plock from plock WHERE `type`='GAME'") != 0;
}
function tryLock(): bool
@@ -1133,7 +1137,7 @@ function tryLock(): bool
$db->update('plock', [
'plock' => 1,
'locktime' => TimeUtil::now(true)
], 'plock=0');
], 'plock=0 AND type="GAME"');
return $db->affectedRows() > 0;
}
@@ -1144,7 +1148,7 @@ function unlock(): bool
$db = DB::db();
$db->update('plock', [
'plock' => 0
], true);
], 'type="GAME"');
return $db->affectedRows() > 0;
}
@@ -1374,6 +1378,7 @@ function CheckHall($no)
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
//TODO: Enum타입을 두종류로 넣고, raw string이면 calcVar에서 받아오면?
$types = [
["experience", 'natural'],
["dedication", 'natural'],
@@ -1403,33 +1408,33 @@ function CheckHall($no)
$generalObj = General::createGeneralObjFromDB($no, null, 2);
$ttw = $generalObj->getRankVar('ttw');
$ttd = $generalObj->getRankVar('ttd');
$ttl = $generalObj->getRankVar('ttl');
$ttw = $generalObj->getRankVar(RankColumn::ttw);
$ttd = $generalObj->getRankVar(RankColumn::ttd);
$ttl = $generalObj->getRankVar(RankColumn::ttl);
$tlw = $generalObj->getRankVar('tlw');
$tld = $generalObj->getRankVar('tld');
$tll = $generalObj->getRankVar('tll');
$tlw = $generalObj->getRankVar(RankColumn::tlw);
$tld = $generalObj->getRankVar(RankColumn::tld);
$tll = $generalObj->getRankVar(RankColumn::tll);
$tsw = $generalObj->getRankVar('tsw');
$tsd = $generalObj->getRankVar('tsd');
$tsl = $generalObj->getRankVar('tsl');
$tsw = $generalObj->getRankVar(RankColumn::tsw);
$tsd = $generalObj->getRankVar(RankColumn::tsd);
$tsl = $generalObj->getRankVar(RankColumn::tsl);
$tiw = $generalObj->getRankVar('tiw');
$tid = $generalObj->getRankVar('tid');
$til = $generalObj->getRankVar('til');
$tiw = $generalObj->getRankVar(RankColumn::tiw);
$tid = $generalObj->getRankVar(RankColumn::tid);
$til = $generalObj->getRankVar(RankColumn::til);
$betWinGold = $generalObj->getRankVar('betwingold');
$betGold = Util::valueFit($generalObj->getRankVar('betgold'), 1);
$betWinGold = $generalObj->getRankVar(RankColumn::betwingold);
$betGold = Util::valueFit($generalObj->getRankVar(RankColumn::betgold), 1);
$win = $generalObj->getRankVar('killnum');
$war = Util::valueFit($generalObj->getRankVar('warnum'), 1);
$win = $generalObj->getRankVar(RankColumn::killnum);
$war = Util::valueFit($generalObj->getRankVar(RankColumn::warnum), 1);
$kill = $generalObj->getRankVar('killcrew');
$death = Util::valueFit($generalObj->getRankVar('deathcrew'), 1);
$kill = $generalObj->getRankVar(RankColumn::killcrew);
$death = Util::valueFit($generalObj->getRankVar(RankColumn::deathcrew), 1);
$killPerson = $generalObj->getRankVar('killcrew_person');
$deathPerson = Util::valueFit($generalObj->getRankVar('deathcrew_person'), 1);
$killPerson = $generalObj->getRankVar(RankColumn::killcrew_person);
$deathPerson = Util::valueFit($generalObj->getRankVar(RankColumn::deathcrew_person), 1);
$tt = Util::valueFit($ttw + $ttd + $ttl, 1);
$tl = Util::valueFit($tlw + $tld + $tll, 1);
@@ -1467,13 +1472,13 @@ function CheckHall($no)
if ($valueType === 'natural') {
$value = $generalObj->getVar($typeName);
} else if ($valueType === 'rank') {
$value = $generalObj->getRankVar($typeName);
$value = $generalObj->getRankVar(RankColumn::from($typeName));
} else if ($valueType === 'calc') {
$value = $calcVar[$typeName];
}
//승률,살상률인데 10회 미만 전투시 스킵
if (($typeName === 'winrate' || $typeName === 'killrate') && $generalObj->getRankVar('warnum') < 10) {
if (($typeName === 'winrate' || $typeName === 'killrate') && $generalObj->getRankVar(RankColumn::warnum) < 10) {
continue;
}
//토너승률인데 50회 미만시 스킵
@@ -1493,7 +1498,7 @@ function CheckHall($no)
continue;
}
//수익률인데 1000미만시 스킵
if ($typeName === 'betrate' && $generalObj->getRankVar('betgold') < 1000) {
if ($typeName === 'betrate' && $generalObj->getRankVar(RankColumn::betgold) < 1000) {
continue;
}
@@ -1581,6 +1586,18 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
}
}
foreach ($db->queryAllLists('SELECT namespace, count(*) as cnt FROM `storage` WHERE namespace LIKE "ut_%" GROUP BY namespace') as [$uniqueNS, $cnt]) {
$itemCode = substr($uniqueNS, 3);
$itemClass = buildItemClass($itemCode);
if (!$itemClass) {
continue;
}
if ($itemClass->isBuyable()) {
continue;
}
$occupiedUnique[$itemCode] = ($occupiedUnique[$itemCode] ?? 0) + $cnt;
}
foreach (GameConst::$allItems as $itemType => $itemCategories) {
if (key_exists($itemType, $invalidItemType)) {
continue;
@@ -1604,7 +1621,8 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
if (!$availableUnique) {
if ($general->getAuxVar('inheritRandomUnique')) {
$general->setAuxVar('inheritRandomUnique', null);
$general->increaseInheritancePoint('previous', GameConst::$inheritItemRandomPoint);
$general->increaseInheritancePoint(InheritanceKey::previous, GameConst::$inheritItemRandomPoint);
$general->increaseRankVar(RankColumn::inherit_point_spent_dynamic, -GameConst::$inheritItemRandomPoint);
$userLogger = new UserLogger($general->getVar('owner'));
$userLogger->push(sprintf("얻을 유니크가 없어 %d 포인트 반환", GameConst::$inheritItemRandomPoint), "inheritPoint");
}
@@ -1620,7 +1638,7 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
$relMonthByInit = Util::joinYearMonth($year, $month) - Util::joinYearMonth($initYear, $initMonth);
$availableBuyUnique = $relMonthByInit >= GameConst::$minMonthToAllowInheritItem;
if($availableBuyUnique){
if ($availableBuyUnique) {
$general->setAuxVar('inheritRandomUnique', null);
}
}
@@ -1674,7 +1692,8 @@ function rollbackInheritUniqueTrial(General $general, string $itemKey, string $r
//두 값이 general, KVStorage 둘다 있고, 이중에선 KVStorage 값을 기준으로 하자 따르자
[,, $amount] = $ownTrial;
$trialStor->deleteValue("u{$ownerID}");
$general->increaseInheritancePoint('previous', $amount);
$general->increaseInheritancePoint(InheritanceKey::previous, $amount);
$general->increaseRankVar(RankColumn::inherit_point_spent_dynamic, -$amount);
LogText("선택유니크 롤백포인트:{$ownerID}", $amount);
$userLogger = new UserLogger($ownerID);
@@ -1739,12 +1758,11 @@ function tryInheritUniqueItem(General $general, string $acquireType = '아이템
$reasons[] = '이미 그 유니크를 가지고 있습니다.';
continue;
}
/*
if (!$ownItem->isBuyable()) {
$reasons[] = '이미 다른 유니크를 가지고 있습니다.';
continue;
}
*/
$availableCnt = $itemList[$itemKey];
$occupiedCnt = $db->queryFirstField('SELECT count(*) FROM general WHERE %b = %s', $itemType, $itemKey);
@@ -1846,6 +1864,9 @@ function tryInheritUniqueItem(General $general, string $acquireType = '아이템
$general->applyDB($db);
//같은 종류의 유니크를 입찰했을 수 있으니 한번 더 검사한다.
tryRollbackInheritUniqueItem($general);
return true;
}
@@ -1889,7 +1910,8 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
LogText("{$general->getName()}, {$general->getID()} 모든 아이템", $trialCnt);
if ($general->getAuxVar('inheritRandomUnique')) {
$general->setAuxVar('inheritRandomUnique', null);
$general->increaseInheritancePoint('previous', GameConst::$inheritItemRandomPoint);
$general->increaseInheritancePoint(InheritanceKey::previous, GameConst::$inheritItemRandomPoint);
$general->increaseRankVar(RankColumn::inherit_point_spent_dynamic, -GameConst::$inheritItemRandomPoint);
$userLogger = new UserLogger($general->getVar('owner'));
$userLogger->push(sprintf("유니크를 얻을 공간이 없어 %d 포인트 반환", GameConst::$inheritItemRandomPoint), "inheritPoint");
}
@@ -1925,8 +1947,8 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
$prob = Util::valueFit($prob, null, 1 / 4); //최대치 감소
$result = false;
$prob /= sqrt(2);
$moreProb = pow(2, 1 / 4);
$prob /= sqrt(7);
$moreProb = pow(10, 1 / 4);
if ($general->getAuxVar('inheritRandomUnique') && $availableBuyUnique) {
//포인트로 랜덤 유니크 획득
@@ -2001,10 +2023,10 @@ function deleteNation(General $lord, bool $applyDB): array
// 전 장수 재야로
foreach ($nationGeneralList as $general) {
$general->setAuxVar(
'max_belong',
InheritanceKey::max_belong->value,
max(
$general->getVar('belong'),
$general->getAuxVar('max_belong') ?? 0
$general->getAuxVar(InheritanceKey::max_belong->value) ?? 0
)
);
$general->setVar('belong', 0);
@@ -2232,7 +2254,7 @@ function calcCityDistance(int $from, int $to, ?array $linkNationList): ?int
* @param $from 기준 도시 코드
* @param $to 대상 도시 코드
* @param $linkNationList 경로에 해당하는 국가 리스트
* @return array $dist=>[cityID, $nation] 배열 가장 앞이 가장 가까움
* @return array<int,array{int,int}[]> $dist=>[cityID, $nation] 배열 가장 앞이 가장 가까움
*/
function searchDistanceListToDest(int $from, int $to, array $linkNationList)
{
@@ -2403,7 +2425,9 @@ function SabotageInjury(array $cityGeneralList, string $reason): int
foreach ($cityGeneralList as $general) {
/** @var General $general */
if (!Util::randBool(0.3)) {
$injuryProb = 0.3;
$injuryProb = $general->onCalcStat($general, 'injuryProb', $injuryProb);
if (!Util::randBool($injuryProb)) {
continue;
}
$general->getLogger()->pushGeneralActionLog($text);
+2
View File
@@ -393,6 +393,7 @@ function setGeneralCommand(int $generalID, array $rawTurnList, string $command,
_setGeneralCommand($commandObj, $turnList);
return [
'result'=>true,
'brief'=>$commandObj->getBrief(),
'reason'=>'success'
];
}
@@ -474,6 +475,7 @@ function setNationCommand(int $generalID, array $turnList, string $command, ?arr
_setNationCommand($commandObj, $turnList);
return [
'result'=>true,
'brief'=>$commandObj->getBrief(),
'arg_test'=>true,
'reason'=>'success'
];
+32 -9
View File
@@ -64,6 +64,15 @@ function getNationLevel(int $level) {
][$level];
}
function convertTournamentType(string $type){
return[
'전력전'=>0,
'통솔전'=>1,
'일기토'=>2,
'설전'=>3,
][$type]??-1;
}
function getGenChar(?string $type) {
if($type === null){
return '-';
@@ -657,7 +666,7 @@ function getDexCall(int $dex) : string {
function getDexLevel(int $dex) : int {
if($dex < 0){
throw new \InvalidArgumentException();
return 0;
}
$retVal = 0;
@@ -692,21 +701,35 @@ function isConsumable(?string $item) : bool{
return $itemClass->isConsumable();
}
function getNameColor(int $npcType):?string{
if($npcType >= 2){
return 'cyan';
}
if($npcType == 1){
function getNPCColor(int $npc): ?string{
if ($npc == 1) {
return 'skyblue';
}
if ($npc == 4){
return 'deepskyblue';
}
if ($npc == 5){
return 'darkcyan';
}
if ($npc == 6){
return 'mediumaquamarine';
}
if ($npc > 1) {
return 'cyan';
}
return null;
}
function getColoredName(string $name, int $npcType):string{
$color = getNameColor($npcType);
function formatName(string $name, int $npc): string
{
$color = getNPCColor($npc);
if($color === null){
return $name;
}
return "<span style='color:{$color}'>{$name}</span>";
return "<span style='color:{$color}'>$name</span>";
}
function ConvertLog(?string $str, $type=1) : string {
+23 -57
View File
@@ -3,6 +3,8 @@
namespace sammo;
use Monolog\Logger;
use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn;
/**
* 게임 룰에 해당하는 함수 모음
@@ -371,7 +373,7 @@ function postUpdateMonthly()
sum(pop)*sum(pop+agri+comm+secu+wall+def)/sum(pop_max+agri_max+comm_max+secu_max+wall_max+def_max)/100
) from city where nation=A.nation and supply=1
))
+(select SUM((ra.value + 1000)/(rb.value + 1000)*(CASE WHEN g.`leadership` >= 40 THEN g.`leadership` ELSE 0 END)*2 + (SQRT(g.intel * g.strength) * 2 + g.leadership / 2)/2)
+(select SUM((ra.value + 1000)/(rb.value + 1000)*(CASE WHEN g.`npc` < 2 THEN 1.2 ELSE 1 END)*(CASE WHEN g.`leadership` >= 40 THEN g.`leadership` ELSE 0 END)*2 + (SQRT(g.intel * g.strength) * 2 + g.leadership / 2)/2)
FROM general AS g
LEFT JOIN `rank_data` AS ra ON g.`no` = ra.general_id AND ra.`type` = \'killcrew_person\'
LEFT JOIN `rank_data` AS rb ON g.`no` = rb.general_id AND rb.`type` = \'deathcrew_person\'
@@ -673,17 +675,17 @@ function updateNationState()
continue;
}
$score = $nationGen->getVar('belong') + 5;
$score = $nationGen->getVar('belong') + 10;
if ($nationGen->getVar('officer_level') == 12) {
$score += 100; //NOTE: 꼬우면 군주하세요.
$score += 60;
} else if ($nationGen->getVar('officer_level') == 11) {
$score += 50;
$score += 30;
} else if ($nationGen->getVar('officer_level') > 4) {
$score += 35;
$score += 15;
}
$score *= $trialCnt;
$score *= 2**$trialCnt;
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
}
@@ -702,7 +704,7 @@ function updateNationState()
if ($chiefID) {
$chiefObj = General::createGeneralObjFromDB($chiefID, ['belong', 'npc', 'aux'], 2);
$chiefObj->increaseInheritancePoint('unifier', 250 * $levelDiff);
$chiefObj->increaseInheritancePoint(InheritanceKey::unifier, 250 * $levelDiff);
$chiefObj->applyDB($db);
}
}
@@ -1022,15 +1024,20 @@ function checkEmperior()
$nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']);
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
foreach (General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc < 2')) as $genObj) {
$inheritPointManager = InheritancePointManager::getInstance();
$allUserGenerals = General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc < 2'));
foreach ($allUserGenerals as $genObj) {
if ($genObj->getNationID() == $nationID) {
if ($genObj->getVar('officer_level') > 4) {
$genObj->increaseInheritancePoint('unifier', 2000);
$genObj->increaseInheritancePoint(InheritanceKey::unifier, 2000);
};
}
$genObj->mergeTotalInheritancePoint(true);
applyInheritanceUser($genObj->getVar('owner'));
$genObj->clearInheritancePoint();
}
processSumInheritPointRank();
foreach ($allUserGenerals as $genObj) {
$inheritPointManager->mergeTotalInheritancePoint($genObj, true);
$inheritPointManager->applyInheritanceUser($genObj->getVar('owner'));
$inheritPointManager->clearInheritancePoint($genObj);
}
$gameStor->isunited = 2;
@@ -1184,55 +1191,14 @@ function checkEmperior()
LogHistory();
}
function applyInheritanceUser(int $userID, bool $isRebirth = false): float
{
//FIXME: 은퇴, 사망, 천통 시점에 바로 반영한다면 여기가 아니라 general class로 이동하는 것이 옳음
//또한 굳이 merge, apply, clean 3단계를 거쳐야 할 이유도 없음
$rebirthDegraded = [
'dex' => 0.5,
];
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}");
$totalPoint = 0;
$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)
{
$maxDomesticCritical = $general->getAuxVar('max_domestic_critical') ?? 0;
$maxDomesticCritical = $general->getAuxVar(InheritanceKey::max_domestic_critical->value) ?? 0;
$maxDomesticCritical += $score / 2;
$general->setAuxVar('max_domestic_critical', $maxDomesticCritical);
$general->setAuxVar(InheritanceKey::max_domestic_critical->value, $maxDomesticCritical);
$oldMaxDomesticCritical = $general->getInheritancePoint('max_domestic_critical');
$oldMaxDomesticCritical = $general->getInheritancePoint(InheritanceKey::max_domestic_critical);
if ($maxDomesticCritical > $oldMaxDomesticCritical) {
$general->setInheritancePoint('max_domestic_critical', $maxDomesticCritical);
$general->setInheritancePoint(InheritanceKey::max_domestic_critical, $maxDomesticCritical);
}
}
+27 -21
View File
@@ -371,10 +371,11 @@ function getGlobalActionLogWithDate(int $year, int $month):array {
return $texts;
}
function LogHistory($isFirst=0) {
function getCurrentHistory($isFirst=false) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$obj = $gameStor->getValues(['startyear', 'year', 'month']);
[$startYear, $year, $month]= $gameStor->getValuesAsArray(['startyear', 'year', 'month']);
$yearMonth = Util::joinYearMonth($year, $month);
$map = getWorldMap([
'year'=>null,
@@ -384,21 +385,14 @@ function LogHistory($isFirst=0) {
'aux'=>[]
]);
$map['month'] = $obj['month'];
$map['year'] = $obj['year'];
$map['startYear'] = $obj['startyear'];
if($isFirst == 1){
$map['month'] -= 1;
if($map['month'] == 0){
$map['month'] = 12;
$map['year'] -= 1;
}
if($isFirst){
$yearMonth -= 1;
}
$year = $map['year'];
$month = $map['month'];
[$year, $month] = Util::parseYearMonth($yearMonth);
$map['startYear'] = $startYear;
$map['year'] = $year;
$map['month'] = $month;
$globalHistory = getGlobalHistoryLogWithDate($year, $month);
$globalAction = getGlobalActionLogWithDate($year, $month);
@@ -418,15 +412,27 @@ function LogHistory($isFirst=0) {
return -($lhs['power']<=>$rhs['power']);
});
$db->insert('ng_history', [
return [
'server_id' => UniqueConst::$serverID,
'year' => $year,
'month' => $month,
'map' => Json::encode($map),
'global_history' => Json::encode($globalHistory),
'global_action' => Json::encode($globalAction),
'nations' => Json::encode($nations),
]);
'map' => $map,
'global_history' => $globalHistory,
'global_action' => $globalAction,
'nations' => $nations,
];
}
function LogHistory($isFirst=false) {
$history = getCurrentHistory($isFirst);
$db = DB::db();
$history['map'] = Json::encode($history['map']);
$history['global_history'] = Json::encode($history['global_history']);
$history['global_action'] = Json::encode($history['global_action']);
$history['nations'] = Json::encode($history['nations']);
$db->insert('ng_history', $history);
return true;
}
+14 -13
View File
@@ -8,11 +8,11 @@ class MapRequest{
public $neutralView;
public $showMe;
function __construct($obj){
$this->serverID = Util::array_get($obj['serverID'], null);
$this->year = Util::array_get($obj['year']);
$this->month = Util::array_get($obj['month']);
$this->aux = Util::array_get($obj['aux'],[]);
$this->neutralView = Util::array_get($obj['neutralView'], false);
$this->serverID = $obj['serverID'] ?? null;
$this->year = $obj['year'] ?? null;
$this->month = $obj['month'] ?? null;
$this->aux = $obj['aux'] ?? [];
$this->neutralView = $obj['neutralView'] ?? false;
$this->showMe = $obj['showMe'];
}
}
@@ -35,7 +35,7 @@ function getHistoryMap($year, $month, ?string $serverID=null){
$map = DB::db()->queryFirstField('SELECT map FROM ng_history WHERE server_id = %s AND year=%i and month=%i',
$serverID,
$year,
$year,
$month);
if(!$map){
@@ -53,7 +53,7 @@ function getWorldMap($req){
if(is_array($req)){
$req = new MapRequest($req);
}
if($req->year && $req->month){
return getHistoryMap($req->year, $req->month, $req->serverID??null);
}
@@ -98,7 +98,7 @@ function getWorldMap($req){
$spyInfo = (object)null;
if($myNation){
$rawSpy = $db->queryFirstField('select `spy` from `nation` where `nation`=%i',
$rawSpy = $db->queryFirstField('select `spy` from `nation` where `nation`=%i',
$myNation);
if(strpos($rawSpy, '|') !== false || is_numeric($rawSpy)){
@@ -123,16 +123,16 @@ function getWorldMap($req){
$nationList = [];
foreach($db->query('select `nation`, `name`, `color`, `capital` from `nation`') as $row){
$nationList[] = [
Util::toInt($row['nation']),
$row['name'],
$row['color'],
Util::toInt($row['nation']),
$row['name'],
$row['color'],
Util::toInt($row['capital'])
];
}
if($myNation){
//굳이 타국 도시에 있는 아국 장수 리스트를 뽑을 이유가 없음. 일단 다 뽑자.
$shownByGeneralList =
$shownByGeneralList =
array_map('\\sammo\\Util::toInt',
$db->queryFirstColumn('select distinct `city` from `general` where `nation` = %i',
$myNation));
@@ -143,7 +143,7 @@ function getWorldMap($req){
$cityList = [];
foreach($db->query('select `city`, `level`, `state`, `nation`, `region`, `supply` from `city`') as $r){
$cityList[] =
$cityList[] =
array_map('\\sammo\\Util::toInt', [$r['city'], $r['level'], $r['state'], $r['nation'], $r['region'], $r['supply']]);
}
@@ -164,6 +164,7 @@ function getWorldMap($req){
'shownByGeneralList' => $shownByGeneralList,
'myCity' => $myCity,
'myNation' => $myNation,
'version' => 0,
'result' => true
];
}
+26 -19
View File
@@ -60,6 +60,10 @@ function chiefTurnTable()
";
}
function templateLimitMsg(string $turntime): string{
return "이미 너무 많은 접속을 하셨습니다. 다음 턴에 다시 시도해주세요. (턴시간: {$turntime})";
}
function displayiActionObjInfo(?iAction $action)
{
if ($action === null) {
@@ -167,6 +171,20 @@ function commandButton(array $opts = [])
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
$showSecret = false;
$permission = checkSecretPermission($me);
$btnClassForTournament = $opts['btnClass'];
if ($opts['isTournamentApplicationOpen']) {
if ($btnClassForTournament != 'dropdown-item') {
$btnClassForTournament = 'toolbarButton2';
}
}
$btnClassForBetting = $opts['btnClass'];
if ($opts['isBettingActive']) {
if ($btnClassForTournament != 'dropdown-item') {
$btnClassForBetting = 'toolbarButton2';
}
}
if ($permission >= 1) {
$showSecret = true;
} else if ($me['officer_level'] == 0) {
@@ -180,6 +198,8 @@ function commandButton(array $opts = [])
'nationLevel' => $nation['level'],
'showSecret' => $showSecret,
'permission' => $permission,
'btnClassForTournament' => $btnClassForTournament,
'btnClassForBetting' => $btnClassForBetting,
], $opts));
}
@@ -215,36 +235,23 @@ function formatLeadershipBonus(int $value): string
return "<font color=cyan>+{$value}</font>";
}
function formatName(string $name, int $npc): string
{
if ($npc == 1) {
$name = "<font color='skyblue'>$name</font>";
} else if ($npc > 1) {
$name = "<font color='cyan'>$name</font>";
}
return $name;
}
function getMapTheme(): string
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$mapTheme = $gameStor->map_theme ?? 'che';
return $mapTheme;
return GameConst::$mapName;
}
function getMapHtml(?string $mapTheme = null)
function getMapHtml(?string $mapName = null)
{
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
if ($mapTheme === null) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$mapTheme = $gameStor->map_theme ?? 'che';
if($mapName === null){
$mapName = GameConst::$mapName;
}
return $templates->render('map', [
'mapTheme' => $mapTheme
'mapName' => $mapName
]);
}
+74 -21
View File
@@ -1,17 +1,68 @@
<?php
namespace sammo;
use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn;
use Ds\Map;
/**
* 시간 단위로 일어나는 이벤트들에 대한 함수 모음
*/
function processSumInheritPointRank(){
$db = DB::db();
$generals = General::createGeneralObjListFromDB(null, null, 2);
$points = new Map();
$points->allocate(count($generals));
foreach($generals as $general){
$generalID = $general->getID();
$points[$generalID] = 0;
}
foreach(InheritanceKey::cases() as $key){
if($key === InheritanceKey::previous){
continue;
}
$subPoints = InheritancePointManager::getInstance()->getInheritancePointFromAll($generals, $key);
foreach($generals as $general){
$generalID = $general->getID();
$points[$generalID] += $subPoints[$generalID] ?? 0;
}
}
$pointsPairs = [];
foreach($points as $generalID => $point){
$pointsPairs[] = [
'nation_id' => $generals[$generalID]->getNationID(),
'general_id' => $generalID,
'type' => RankColumn::inherit_point_earned_by_merge->value,
'value' => $point,
];
}
//XXX: multiple batch update가 제공되지 않으므로..
$db->delete('rank_data', '`type` = %s', RankColumn::inherit_point_earned_by_merge->value);
$db->insert('rank_data', $pointsPairs);
$db->query(
'UPDATE `rank_data` D SET `value` = (SELECT SUM(`value`) FROM `rank_data` S WHERE S.general_id = D.general_id AND S.`type` IN %ls) WHERE D.`type` = %s',
[RankColumn::inherit_point_earned_by_action->value, RankColumn::inherit_point_earned_by_merge->value],
RankColumn::inherit_point_earned->value
);
$db->query(
'UPDATE `rank_data` D SET `value` = (SELECT `value` FROM `rank_data` S WHERE S.general_id = D.general_id AND S.`type` = %s) WHERE D.`type` = %s',
RankColumn::inherit_point_spent_dynamic->value,
RankColumn::inherit_point_spent->value
);
}
//1월마다 실행
function processSpring() {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
//인구 증가
popIncrease();
// 1월엔 무조건 내정 1% 감소
$db->update('city',[
'dead'=>0,
@@ -22,6 +73,9 @@ function processSpring() {
'wall'=>$db->sqleval('wall * 0.99'),
],true);
//인구 증가
popIncrease();
// > 10000 유지비 3%, > 1000 유지비 1%
// 유지비 1%
$db->update('general', [
@@ -40,7 +94,7 @@ function processSpring() {
function processGoldIncome() {
$db = DB::db();
$gameStor = new KVStorage($db, 'game_env');
$gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$adminLog = [];
@@ -100,7 +154,7 @@ function processGoldIncome() {
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false);
$gold = Util::round(getBill($generalObj->getVar('dedication'))*$ratio);
$generalObj->increaseVar('gold', $gold);
$logger = $generalObj->getLogger();
if($generalObj->getVar('officer_level') > 4){
$logger->pushGeneralActionLog($incomeLog, $logger::PLAIN);
@@ -121,9 +175,9 @@ function processGoldIncome() {
function popIncrease() {
$db = DB::db();
$nationList = $db->queryAllLists('SELECT nation,rate_tmp,type FROM nation');
// 인구 및 민심
$db->update('city', [
@@ -138,7 +192,7 @@ function popIncrease() {
foreach($nationList as [$nationID, $taxRate, $nationType]){
$nationTypeObj = buildNationTypeClass($nationType);
$popRatio = (30 - $taxRate)/200; // 20일때 5% 5일때 12.5% 50일때 -10%
$popRatio = $nationTypeObj->onCalcNationalIncome('pop', $popRatio);
@@ -246,7 +300,7 @@ function getGoldIncome(int $nationID, int $nationLevel, float $taxRate, int $cap
}
$cityIncome *= ($taxRate / 20);
return $cityIncome;
}
@@ -290,9 +344,6 @@ function getWarGoldIncome(string $nationType, array $cityList){
function processFall() {
$db = DB::db();
//인구 증가
popIncrease();
// 7월엔 무조건 내정 1% 감소
$db->update('city',[
'dead'=>0,
@@ -303,6 +354,8 @@ function processFall() {
'wall'=>$db->sqleval('wall * 0.99'),
],true);
//인구 증가
popIncrease();
// > 10000 유지비 3%, > 1000 유지비 1%
// 유지비 1%
@@ -378,7 +431,7 @@ function processRiceIncome() {
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false);
$rice = Util::round(getBill($generalObj->getVar('dedication'))*$ratio);
$generalObj->increaseVar('rice', $rice);
$logger = $generalObj->getLogger();
if($generalObj->getVar('officer_level') > 4){
$logger->pushGeneralActionLog($incomeLog, $logger::PLAIN);
@@ -418,7 +471,7 @@ function getRiceIncome(int $nationID, int $nationLevel, float $taxRate, int $cap
}
$cityIncome *= ($taxRate / 20);
return $cityIncome;
}
@@ -439,12 +492,12 @@ function getWallIncome(int $nationID, int $nationLevel, float $taxRate, int $cap
$cityIncome = 0;
foreach($cityList as $rawCity){
$cityID = $rawCity['city'];
$cityIncome += calcCityWallRiceIncome($rawCity, $officersCnt[$cityID]??0, $capitalID == $cityID, $nationLevel, $nationTypeObj);
}
$cityIncome *= ($taxRate / 20);
return $cityIncome;
}
@@ -520,7 +573,7 @@ function disaster() {
}
else {
$raiseProp = 0.06 - ($city['secu'] / $city['secu_max']) * 0.05; // 1 ~ 6%
}
}
if(Util::randBool($raiseProp)) {
$targetCityList[] = $city;
@@ -576,7 +629,7 @@ function disaster() {
$logger->flush();
if (!$isGood) {
$generalListByCity = Util::arrayGroupBy($db->query('SELECT no, nation, city, injury, crew, atmos, train FROM general WHERE city IN %li', Util::squeezeFromArray($targetCityList, 'city')), 'city');
$generalListByCity = Util::arrayGroupBy($db->query('SELECT no, name, nation, city, officer_level, injury, leadership, strength, intel, horse, weapon, book, item, crew, crewtype, atmos, train, special, special2 FROM general WHERE city IN %li', Util::squeezeFromArray($targetCityList, 'city')), 'city');
//NOTE: 쿼리 1번이지만 복잡하기 vs 쿼리 여러번이지만 조금 더 깔끔하기
foreach ($targetCityList as $city) {
$affectRatio = Util::valueFit($city['secu'] / $city['secu_max'] / 0.8, 0, 1);
@@ -592,11 +645,11 @@ function disaster() {
'def'=>$db->sqleval('def * %d', $affectRatio),
'wall'=>$db->sqleval('wall * %d', $affectRatio),
], 'city = %i', $city['city']);
$generalList = array_map(
function($rawGeneral) use ($city, $year, $month){
return new General($rawGeneral, null, $city, null, $year, $month, false);
},
},
$generalListByCity[$city['city']]??[]
);
@@ -619,7 +672,7 @@ function disaster() {
'wall'=>$db->sqleval('least(wall * %d, wall_max)', $affectRatio),
], 'city = %i', $city['city']);
}
}
+229 -619
View File
@@ -2,13 +2,15 @@
namespace sammo;
use sammo\DTO\BettingInfo;
use sammo\Enums\InheritanceKey;
function processTournament()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'tnmt_auto', 'tnmt_time']);
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'tnmt_auto', 'tnmt_time', 'last_tournament_betting_id']);
$now = new \DateTime();
$offset = $now->getTimestamp() - (new \DateTime($admin['tnmt_time']))->getTimestamp();
@@ -26,30 +28,17 @@ function processTournament()
}
//현시간이 스탬프 지나친경우
switch ($admin['tnmt_auto']) {
case 1:
$unit = 720;
break;
case 2:
$unit = 420;
break;
case 3:
$unit = 180;
break;
case 4:
$unit = 60;
break;
case 5:
$unit = 30;
break;
case 6:
$unit = 15;
break;
case 7:
$unit = 5;
break;
default:
throw new MustNotBeReachedException();
$unit = [
1 => 720,
2 => 420,
3 => 180,
4 => 60,
5 => 30,
6 => 15,
7 => 5,
][$admin['tnmt_auto']] ?? null;
if($unit === null){
throw new MustNotBeReachedException();
}
//업데이트 횟수
@@ -90,9 +79,12 @@ function processTournament()
final16set();
$tnmt = 6;
$phase = 0;
startBetting();
startBetting($type, $unit);
break;
case 6: //베팅중
$bettingID = $admin['last_tournament_betting_id'];
$betting = new Betting($bettingID);
$betting->closeBetting();
$tnmt = 7;
$phase = 0;
break;
@@ -164,40 +156,48 @@ function processTournament()
$gameStor->tnmt_time = (new \DateTimeImmutable($admin['tnmt_time']))->add(new \DateInterval("PT{$second}S"))->format('Y-m-d H:i:s');
}
function getTournamentTerm()
function getTournamentTerm(): ?int
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$tnmt_auto = $gameStor->tnmt_auto;
switch ($tnmt_auto) {
case 0:
$str = '';
break;
case 1:
$str = "경기당 12분";
break;
case 2:
$str = "경기당 7분";
break;
case 3:
$str = "경기당 3분";
break;
case 4:
$str = "경기당 1분";
break;
case 5:
$str = "경기당 30초";
break;
case 6:
$str = "경기당 15초";
break;
case 7:
$str = "경기당 5초";
break;
if ($tnmt_auto === null) {
$tnmt_auto = $gameStor->tnmt_trig;
}
return $str;
return [
0 => null,
1 => 12 * 60,
2 => 7 * 60,
3 => 3 * 60,
4 => 1 * 60,
5 => 30,
6 => 15,
7 => 5,
][$tnmt_auto] ?? null;
}
function getTournamentTermText()
{
$term = getTournamentTerm();
if ($term === null) {
return '수동';
}
if ($term % 60 === 0) {
$termMin = intdiv($term, 60);
return "경기당 {$termMin}";
}
if ($term > 60) {
$termSec = $term % 60;
$termMin = intdiv($term, 60);
return "경기당 {$termMin}{$termSec}";
}
return "경기당 {$term}";
}
function getTournamentTime()
@@ -256,15 +256,13 @@ function getTournament(int $tnmt)
][$tnmt] ?? "TOURNAMENT_TYPE_ERR_{$tnmt}";
}
function printRow($k, $npc, $name, $abil, $tgame, $win, $draw, $lose, $gd, $gl, $prmt)
function printRow(int $k, int $npc, string $name, $abil, $tgame, $win, $draw, $lose, $gd, $gl, $prmt)
{
$k += 1;
if ($prmt > 0) {
$name = "<font color=orange>" . $name . "</font>";
} elseif ($npc >= 2) {
$name = "<font color=cyan>" . $name . "</font>";
} elseif ($npc == 1) {
$name = "<font color=skyblue>" . $name . "</font>";
} else if ($npc > 0) {
$name = formatName($name, $npc);
}
echo "<tr align=center><td class='bg2'>$k</td><td style='font-size:80%;'>$name</td><td>$abil</td><td>$tgame</td><td>$win</td><td>$draw</td><td>$lose</td><td>$gd</td><td>$gl</td></tr>";
}
@@ -329,32 +327,15 @@ function startTournament($auto, $type)
eraseTnmtFightLogAll();
switch ($auto) {
case 1:
$unit = 60;
break;
case 2:
$unit = 60;
break;
case 3:
$unit = 60;
break;
case 4:
$unit = 60;
break;
case 5:
$unit = 30;
break;
case 6:
$unit = 15;
break;
case 7:
$unit = 5;
break;
default:
$unit = 60;
break;
}
$unit = [
1 => 60,
2 => 60,
3 => 60,
4 => 60,
5 => 30,
6 => 15,
7 => 5,
][$auto] ?? 60;
$admin = $gameStor->getValues(['year', 'month']);
@@ -362,29 +343,12 @@ function startTournament($auto, $type)
$gameStor->tnmt_time = (new \DateTimeImmutable())->add(new \DateInterval("PT{$unit}M"))->format('Y-m-d H:i:s');
$gameStor->tournament = 1;
$gameStor->tnmt_type = $type;
$gameStor->last_tournament_betting_id = 0;
$gameStor->phase = 0;
$db->update('general', [
'tournament' => 0,
], true);
$db->update('betting', [
'bet0' => 0,
'bet1' => 0,
'bet2' => 0,
'bet3' => 0,
'bet4' => 0,
'bet5' => 0,
'bet6' => 0,
'bet7' => 0,
'bet8' => 0,
'bet9' => 0,
'bet10' => 0,
'bet11' => 0,
'bet12' => 0,
'bet13' => 0,
'bet14' => 0,
'bet15' => 0
], true);
$db->query('TRUNCATE TABLE tournament');
$opener = $db->queryFirstField('SELECT `general`.`name` FROM `general` JOIN `nation` ON `general`.`nation` = `nation`.`nation` WHERE `general`.`officer_level` = 12 AND `nation`.`level` = 7 ORDER BY rand() LIMIT 1');
@@ -411,44 +375,90 @@ function startTournament($auto, $type)
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
}
function startBetting()
function getDummyBettingInfo(string $tnmt_type): BettingInfo
{
return new BettingInfo(
id: 0,
type: 'tournament',
name: $tnmt_type,
finished: true,
selectCnt: 1,
reqInheritancePoint: false,
openYearMonth: 0,
closeYearMonth: 0,
candidates: []
);
}
function startBetting($type, $unit)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month, $startyear] = $gameStor->getValuesAsArray(['year', 'month', 'startyear']);
[$year, $month, $startyear, $turnterm] = $gameStor->getValuesAsArray(['year', 'month', 'startyear', 'turnterm']);
pushGlobalHistoryLog([
"<S>◆</>{$year}{$month}월:<B><b>【대회】</b></>우승자를 예상하는 <C>내기</>가 진행중입니다! 호사가의 참여를 기다립니다!"
], $year, $month);
[$typeText, $statName, $statKey] = [
['전력전', '종능', 'total'],
['통솔전', '통솔', 'leadership'],
['일기토', '무력', 'strength'],
['설전', '지력', 'intel'],
][$type];
$bettingID = Betting::genNextBettingID();
//어차피 강제로 닫을 것이므로 크게 신경쓰지 않는다.
$openYearMonth = Util::joinYearMonth($year, $month);
$closeYearMonth = $openYearMonth + 120;
/** @var \sammo\DTO\SelectItem[] */
$candidates = [];
$generalList = $db->query('SELECT no,npc,name,win,leadership,strength,intel,leadership+strength+intel as total from tournament where grp>=20 order by grp, grp_no LIMIT 16');
foreach ($generalList as $idx => $general) {
if ($general['no'] <= 0) {
continue;
}
$general['idx'] = $idx;
$candidates[$general['no']] = new \sammo\DTO\SelectItem(
title: $general['name'],
info: "{$statName}: {$general[$statKey]}",
aux: $general
);
}
$candidateCnt = count($candidates);
Betting::openBetting(new BettingInfo(
id: $bettingID,
type: 'tournament',
name: $typeText,
finished: false,
selectCnt: 1,
reqInheritancePoint: false,
openYearMonth: $openYearMonth,
closeYearMonth: $closeYearMonth,
candidates: $candidates,
));
$betting = new Betting($bettingID);
$gameStor->last_tournament_betting_id = $bettingID;
$betGold = Util::valueFit(floor((3 + $year - $startyear) * 0.334) * 10, 10);
$npcList = $db->queryFirstColumn('SELECT no FROM general WHERE npc >= 2 AND gold >= (500 + %i)', $betGold);
$npcBet = [];
$betSum = [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
];
$targetList = array_keys($candidates);
foreach ($npcList as $npcID) {
$target = Util::randRangeInt(0, 15);
$betSum[$target] += $betGold;
$target = Util::choiceRandom($targetList);
$npcBet[] = [$npcID, $target];
}
$db->update('general', [
'gold' => $db->sqleval('gold - %i', $betGold),
], 'no IN %li', $npcList);
foreach ($npcBet as [$npcID, $betTarget]) {
$targetKey = "bet{$betTarget}";
$db->update('betting', [
"bet{$betTarget}" => $db->sqleval('%b + %i', $targetKey, $betGold),
], 'general_id = %i', $npcID);
}
foreach ($betSum as $betTarget => $betSumGold) {
$targetKey = "bet{$betTarget}";
$db->update('betting', [
"bet{$betTarget}" => $db->sqleval('%b + %i', $targetKey, $betSumGold),
], 'general_id = 0');
$betting->bet($npcID, null, [$betTarget], $betGold);
}
}
@@ -507,24 +517,26 @@ function fillLowGenAll($tnmt_type)
};
//자동신청하고, 돈 있고, 아직 참가 안한 장수
/** @var array<array{0:array,1:float}> */
$freeJoinerCandidate = [];
foreach($db->query(
foreach ($db->query(
'SELECT no,npc,name,leadership,strength,intel,explevel,horse,weapon,book from general where tnmt=1 and tournament=0',
) as $gen){
) as $gen) {
$score = $scoringCandFunction($gen);
$freeJoinerCandidate[$gen['no']] = [$gen, $score**2];
$freeJoinerCandidate[$gen['no']] = [$gen, $score ** 1.5];
}
$joinersValues = [];
$joinersIdx = [];
foreach(Util::range($toBeFilledCnt) as $_){
if(!$freeJoinerCandidate){
foreach (Util::range($toBeFilledCnt) as $_) {
if (!$freeJoinerCandidate) {
break;
}
$general = Util::choiceRandomUsingWeightPair($freeJoinerCandidate);
/** @var array $general */
unset($freeJoinerCandidate[$general['no']]);
$grpIdx = array_keys($grpCount, min($grpCount))[0];
@@ -576,160 +588,37 @@ function fillLowGenAll($tnmt_type)
//7 8강
//8 4강
//9 결승
function getTwo($tournament, $phase)
/**
* @return array{0:int,1:int}
*/
function getTwo(int $tournament, int $phase): array
{
$cand = [];
switch ($tournament) {
case 2:
//예선
switch ($phase % 28) {
case 0:
$cand[0] = 0;
$cand[1] = 1;
break;
case 1:
$cand[0] = 2;
$cand[1] = 3;
break;
case 2:
$cand[0] = 4;
$cand[1] = 5;
break;
case 3:
$cand[0] = 6;
$cand[1] = 7;
break;
case 4:
$cand[0] = 0;
$cand[1] = 2;
break;
case 5:
$cand[0] = 1;
$cand[1] = 3;
break;
case 6:
$cand[0] = 4;
$cand[1] = 6;
break;
case 7:
$cand[0] = 5;
$cand[1] = 7;
break;
case 8:
$cand[0] = 0;
$cand[1] = 3;
break;
case 9:
$cand[0] = 1;
$cand[1] = 6;
break;
case 10:
$cand[0] = 2;
$cand[1] = 5;
break;
case 11:
$cand[0] = 4;
$cand[1] = 7;
break;
case 12:
$cand[0] = 0;
$cand[1] = 4;
break;
case 13:
$cand[0] = 1;
$cand[1] = 5;
break;
case 14:
$cand[0] = 2;
$cand[1] = 6;
break;
case 15:
$cand[0] = 3;
$cand[1] = 7;
break;
case 16:
$cand[0] = 0;
$cand[1] = 5;
break;
case 17:
$cand[0] = 1;
$cand[1] = 4;
break;
case 18:
$cand[0] = 2;
$cand[1] = 7;
break;
case 19:
$cand[0] = 3;
$cand[1] = 6;
break;
case 20:
$cand[0] = 0;
$cand[1] = 6;
break;
case 21:
$cand[0] = 1;
$cand[1] = 7;
break;
case 22:
$cand[0] = 2;
$cand[1] = 4;
break;
case 23:
$cand[0] = 3;
$cand[1] = 5;
break;
case 24:
$cand[0] = 0;
$cand[1] = 7;
break;
case 25:
$cand[0] = 1;
$cand[1] = 2;
break;
case 26:
$cand[0] = 3;
$cand[1] = 4;
break;
case 27:
$cand[0] = 5;
$cand[1] = 6;
break;
}
$candMap = [
[0, 1], [2, 3], [4, 5], [6, 7],
[0, 2], [1, 3], [4, 6], [5, 7],
[0, 3], [1, 6], [2, 5], [4, 7],
[0, 4], [1, 5], [2, 6], [3, 7],
[0, 5], [1, 4], [2, 7], [3, 6],
[0, 6], [1, 7], [2, 4], [3, 5],
[0, 7], [1, 2], [3, 4], [5, 6],
];
$cand = $candMap[$phase % 28];
if ($phase >= 28) {
$temp = $cand[0];
$cand[0] = $cand[1];
$cand[1] = $temp;
$cand = [$cand[1], $cand[0]];
}
break;
case 4:
//본선
switch ($phase % 6) {
case 0:
$cand[0] = 0;
$cand[1] = 1;
break;
case 1:
$cand[0] = 2;
$cand[1] = 3;
break;
case 2:
$cand[0] = 0;
$cand[1] = 2;
break;
case 3:
$cand[0] = 1;
$cand[1] = 3;
break;
case 4:
$cand[0] = 0;
$cand[1] = 3;
break;
case 5:
$cand[0] = 1;
$cand[1] = 2;
break;
}
$candMap = [
[0, 1], [2, 3],
[0, 2], [1, 3],
[0, 3], [1, 2],
];
$cand = $candMap[$phase % 6];
break;
}
return $cand;
@@ -922,29 +811,14 @@ function finalFight($tnmt_type, $tnmt, $phase, $type)
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
switch ($type) {
case 16:
$offset = 20;
$turn = 7;
$next = 7;
break;
case 8:
$offset = 30;
$turn = 3;
$next = 8;
break;
case 4:
$offset = 40;
$turn = 1;
$next = 9;
break;
case 2:
$offset = 50;
$turn = 0;
$next = 0;
break;
default:
throw new MustNotBeReachedException();
[$offset, $turn, $next] = [
16 => [20, 7, 7],
8 => [30, 3, 8],
4 => [40, 1, 9],
2 => [50, 0, 0],
][$type] ?? [0, 0, 0];
if ($offset === 0) {
throw new MustNotBeReachedException();
}
$grp = $phase + $offset;
@@ -982,29 +856,18 @@ function setGift($tnmt_type, $tnmt, $phase)
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month', 'develcost']);
$admin = $gameStor->getValues(['year', 'month', 'develcost', 'last_tournament_betting_id']);
$resultHelper = [];
switch ($tnmt_type) {
case 0:
$tp = "전력전";
$tp2 = "tt";
break;
case 1:
$tp = "통솔전";
$tp2 = "tl";
break;
case 2:
$tp = "일기토";
$tp2 = "ts";
break;
case 3:
$tp = "설전";
$tp2 = "ti";
break;
default:
throw new MustNotBeReachedException();
[$tp, $tp2] = [
0 => ['전력전', 'tt'],
1 => ['통솔전', 'tl'],
2 => ['일기토', 'ts'],
3 => ['설전', 'ti'],
][$tnmt_type] ?? [null, null];
if($tp === null || $tp2 === null){
throw new MustNotBeReachedException();
}
//16강자 명성 돈
@@ -1063,7 +926,7 @@ function setGift($tnmt_type, $tnmt, $phase)
//포상 장수 이름, 금액
$resultHelper[$generalID]['reward'] += $cost;
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>4강 진출</span>";
General::createGeneralObjFromDB($generalID)->increaseInheritancePoint('tournament', 10);
General::createGeneralObjFromDB($generalID)->increaseInheritancePoint(InheritanceKey::tournament, 10);
}
//결승자 명성 돈
$cost = $admin['develcost'] * 6;
@@ -1135,39 +998,19 @@ function setGift($tnmt_type, $tnmt, $phase)
$logger = $general['logger'];
$logger->pushGeneralActionLog("<C>{$tp}</> 대회의 {$general['msg']}로 <C>{$rewardText}</>의 <S>상금</>, 약간의 <S>명성</> 획득!", ActionLogger::EVENT_PLAIN);
//TODO: 토너먼트의 다른 값이 모두 sql에 직접 입력하므로 기반을 바꿔야함.
$generalObjList[$generalID]->increaseInheritancePoint('tournament', $general['inheritance_point']);
$generalObjList[$generalID]->increaseInheritancePoint(InheritanceKey::tournament, $general['inheritance_point']);
}
//우승자 번호
$winnerGrp = $resultHelper[$winner['no']]['grp'];
$winnerGrpNo = $resultHelper[$winner['no']]['grp_no'];
$winnerSlot = ($winnerGrp - 20) * 2 + $winnerGrpNo;
//당첨칸에 베팅한 사람들만
$globalBet = $db->queryFirstList('SELECT * FROM betting WHERE general_id = 0');
$globalBet = array_splice($globalBet, -16);
$globalBetTotal = array_sum($globalBet);
$rewardRate = round($globalBetTotal / max($globalBet[$winnerSlot], 1), 2);
$betKey = "bet{$winnerSlot}";
$gambleResult = Util::convertArrayToDict($db->query('SELECT general_id, %b as bet FROM betting WHERE %b > 0 AND general_id > 0', $betKey, $betKey), 'general_id');
foreach (General::createGeneralObjListFromDB(Util::squeezeFromArray($gambleResult, 'general_id'), ['gold', 'npc'], 1) as $gambler) {
$reward = Util::round($gambleResult[$gambler->getID()]['bet'] * $rewardRate);
$gambler->increaseVar('gold', $reward);
if (($gambler->getNPCType() == 0) || ($gambler->getNPCType() == 1 && $gambler->getRankVar('betgold', 0) > 0)) {
$gambler->increaseRankVar('betwingold', $reward);
$gambler->increaseRankVar('betwin', 1);
}
$rewardText = number_format($reward);
$gambler->getLogger()->pushGeneralActionLog("<C>{$tp}</> 대회의 베팅 당첨으로 <C>{$rewardText}</>의 <S>금</> 획득!", ActionLogger::EVENT_PLAIN);
$gambler->applyDB($db);
}
$bettingID = $gameStor->last_tournament_betting_id;
$betting = new Betting($bettingID);
$betting->giveReward([$winner['no']]);
}
function setRefund()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
//16강자 명성 돈
@@ -1178,9 +1021,13 @@ function setRefund()
], 'no IN %li', $generalIDList);
//베팅금 환수
$db->update(['general', [
'gold' => $db->sqleval('gold + (SELECT bet0+bet1+bet2+bet3+bet4+bet5+bet6+bet7+bet8+bet9+bet10+bet11+bet12+bet13+bet14+bet15 FROM betting WHERE general_id = general.no)')
]], true);
$bettingID = $gameStor->last_tournament_betting_id ?? 0;
if ($bettingID != 0) {
$betting = new Betting($bettingID);
if (!$betting->getInfo()->finished) {
$betting->giveReward([-1]);
}
}
//자동진행 끝
$gameStor->tnmt_auto = 0;
@@ -1214,19 +1061,15 @@ function fight($tnmt_type, $tnmt, $phs, $group, $g1, $g2, $type)
$turn = 100;
}
[$tp, $tp2] = [
0 => ['total', 'tt'],
1 => ['leadership', 'tl'],
2 => ['strength', 'ts'],
3 => ['intel', 'ti'],
][$tnmt_type] ?? [null, null];
if ($tnmt_type == 1) {
$tp = "leadership";
$tp2 = "tl";
} elseif ($tnmt_type == 2) {
$tp = "strength";
$tp2 = "ts";
} elseif ($tnmt_type == 3) {
$tp = "intel";
$tp2 = "ti";
} else /*$tnmt_type == 0*/ {
$tp = "total";
$tp2 = "tt";
if($tp === null || $tp2 === null){
throw new MustNotBeReachedException($tnmt_type);
}
$e1 = $energy1 = Util::round($gen1[$tp] * getLog($gen1['lvl'], $gen2['lvl']) * 10);
@@ -1333,303 +1176,70 @@ function fight($tnmt_type, $tnmt, $phs, $group, $g1, $g2, $type)
} // 10~50
$critical1 = 0;
$critical2 = 0;
$crticialSkillMap = [
0 => ['전력', '집중'],
1 => ['봉시진', '어린진'],
2 => ['삼단', '나선'],
3 => ['독설', '논파'],
];
$fatalitySkillMap = [
0 => '압도',
1 => '팔문금쇄진',
2 => '일격 필살',
3 => '모독 욕설'
];
$skillMap = [
0 => ['참격', '집중', '역공', '반격', '선제', '도발'],
1 => ['추행진', '학익진', '장사진', '형액진', '기형진', '구행진'],
2 => ['기합', '기염', '반격', '역공', '삼단', '나선'],
3 => ['논파', '항변', '반론', '반박', '도발', '면박'],
];
//막판 분노
$ratio = rand() % 300;
if ($e1 / 5 > $energy1 && $damage1 > $damage2 && $gen1[$tp] >= $ratio) {
$damage2 *= Util::round((rand() % 301 + 200) / 100); // 200 ~ 500%
$critical1 = 1;
if ($tnmt_type == 0) {
switch (rand() % 2) {
case 0:
$str = "전력";
break;
case 1:
$str = "집중";
break;
}
} elseif ($tnmt_type == 1) {
switch (rand() % 2) {
case 0:
$str = "봉시진";
break;
case 1:
$str = "어린진";
break;
}
} elseif ($tnmt_type == 2) {
switch (rand() % 2) {
case 0:
$str = "삼단";
break;
case 1:
$str = "나선";
break;
}
} elseif ($tnmt_type == 3) {
switch (rand() % 2) {
case 0:
$str = "독설";
break;
case 1:
$str = "논파";
break;
}
}
$str = Util::choiceRandom($crticialSkillMap[$tnmt_type]);
$log[] = "<S>●</> <Y>{$gen1['name']}</>의 분노의 <M>{$str}</> 공격!";
}
$ratio = rand() % 300;
if ($e2 / 5 > $energy2 && $damage2 > $damage1 && $gen2[$tp] >= $ratio) {
$damage1 *= Util::round((rand() % 301 + 200) / 100); // 200 ~ 500%
$critical2 = 1;
if ($tnmt_type == 0) {
switch (rand() % 2) {
case 0:
$str = "전력";
break;
case 1:
$str = "집중";
break;
}
} elseif ($tnmt_type == 1) {
switch (rand() % 2) {
case 0:
$str = "봉시진";
break;
case 1:
$str = "어린진";
break;
}
} elseif ($tnmt_type == 2) {
switch (rand() % 2) {
case 0:
$str = "삼단";
break;
case 1:
$str = "나선";
break;
}
} elseif ($tnmt_type == 3) {
switch (rand() % 2) {
case 0:
$str = "독설";
break;
case 1:
$str = "논파";
break;
}
}
$str = Util::choiceRandom($crticialSkillMap[$tnmt_type]);
$log[] = "<S>●</> <Y>{$gen2['name']}</>의 분노의 <M>{$str}</> 공격!";
}
//1합 승부
if ($phase == 1) {
$ratio = rand() % 400;
if ($gen1[$tp] * 0.9 > $gen2[$tp] && $gen1[$tp] >= $ratio) {
$damage1 = 0;
$damage2 = $e2;
if ($tnmt_type == 0) {
$log[] = "<S>●</> <Y>{$gen1['name']}</>의 <M>압도</>!";
} elseif ($tnmt_type == 1) {
$log[] = "<S>●</> <Y>{$gen1['name']}</>의 <M>팔문금쇄진</>!";
} elseif ($tnmt_type == 2) {
$log[] = "<S>●</> <Y>{$gen1['name']}</>의 <M>일격 필살</>!";
} elseif ($tnmt_type == 3) {
$log[] = "<S>●</> <Y>{$gen1['name']}</>의 <M>모독 욕설</>!";
}
$log[] = "<S>●</> <Y>{$gen1['name']}</>의 <M>{$fatalitySkillMap[$tnmt_type]}</>!";
}
if ($gen2[$tp] * 0.9 > $gen1[$tp] && $gen2[$tp] >= $ratio) {
$damage2 = 0;
$damage1 = $e1;
if ($tnmt_type == 0) {
$log[] = "<S>●</> <Y>{$gen2['name']}</>의 <M>압도</>!";
} elseif ($tnmt_type == 1) {
$log[] = "<S>●</> <Y>{$gen2['name']}</>의 <M>팔문금쇄진</>!";
} elseif ($tnmt_type == 2) {
$log[] = "<S>●</> <Y>{$gen2['name']}</>의 <M>일격 필살</>!";
} elseif ($tnmt_type == 3) {
$log[] = "<S>●</> <Y>{$gen2['name']}</>의 <M>모독 욕설</>!";
}
$log[] = "<S>●</> <Y>{$gen2['name']}</>의 <M>{$fatalitySkillMap[$tnmt_type]}</>!";
}
} else {
$ratio = rand() % 1000;
if ($critical1 == 0 && $gen1[$tp] >= $ratio) {
$damage2 *= Util::randRangeInt(150, 300) / 100; // 150 ~ 300%
$critical1 = 1;
if ($tnmt_type == 0) {
switch (rand() % 6) {
case 0:
$str = "참격";
break;
case 1:
$str = "집중";
break;
case 2:
$str = "역공";
break;
case 3:
$str = "반격";
break;
case 4:
$str = "선제";
break;
case 5:
$str = "도발";
break;
}
} elseif ($tnmt_type == 1) {
switch (rand() % 6) {
case 0:
$str = "추행진";
break;
case 1:
$str = "학익진";
break;
case 2:
$str = "장사진";
break;
case 3:
$str = "형액진";
break;
case 4:
$str = "기형진";
break;
case 5:
$str = "구행진";
break;
}
} elseif ($tnmt_type == 2) {
switch (rand() % 6) {
case 0:
$str = "기합";
break;
case 1:
$str = "기염";
break;
case 2:
$str = "반격";
break;
case 3:
$str = "역공";
break;
case 4:
$str = "삼단";
break;
case 5:
$str = "나선";
break;
}
} elseif ($tnmt_type == 3) {
switch (rand() % 6) {
case 0:
$str = "논파";
break;
case 1:
$str = "항변";
break;
case 2:
$str = "반론";
break;
case 3:
$str = "반박";
break;
case 4:
$str = "도발";
break;
case 5:
$str = "면박";
break;
}
}
$str = Util::choiceRandom($skillMap[$tnmt_type]);
$log[] = "<S>●</> <Y>{$gen1['name']}</>의 <M>{$str}</>!";
}
$ratio = rand() % 1000;
if ($critical2 == 0 && $gen2[$tp] >= $ratio) {
$damage1 *= Util::randRangeInt(150, 300) / 100; // 150 ~ 300%
$critical2 = 1;
if ($tnmt_type == 0) {
switch (rand() % 6) {
case 0:
$str = "참격";
break;
case 1:
$str = "집중";
break;
case 2:
$str = "역공";
break;
case 3:
$str = "반격";
break;
case 4:
$str = "선제";
break;
case 5:
$str = "도발";
break;
}
} elseif ($tnmt_type == 1) {
switch (rand() % 6) {
case 0:
$str = "추행진";
break;
case 1:
$str = "학익진";
break;
case 2:
$str = "장사진";
break;
case 3:
$str = "형액진";
break;
case 4:
$str = "기형진";
break;
case 5:
$str = "구행진";
break;
}
} elseif ($tnmt_type == 2) {
switch (rand() % 6) {
case 0:
$str = "기합";
break;
case 1:
$str = "기염";
break;
case 2:
$str = "반격";
break;
case 3:
$str = "역공";
break;
case 4:
$str = "삼단";
break;
case 5:
$str = "나선";
break;
}
} elseif ($tnmt_type == 3) {
switch (rand() % 6) {
case 0:
$str = "논파";
break;
case 1:
$str = "항변";
break;
case 2:
$str = "반론";
break;
case 3:
$str = "반박";
break;
case 4:
$str = "도발";
break;
case 5:
$str = "면박";
break;
}
}
$str = Util::choiceRandom($skillMap[$tnmt_type]);
$log[] = "<S>●</> <Y>{$gen2['name']}</>의 <M>{$str}</>!";
}
}
BIN
View File
Binary file not shown.
-684
View File
@@ -1,684 +0,0 @@
상성 이름 사진 국가 도시 통 무 지 급 출생 사망 꿈 특기
1, "소제1",1001, 0, "낙양", 20, 11, 48, 0, 168, 190, "유지", "-"); $gencount++;
1, "헌제",1002, 0, "낙양", 17, 13, 61, 0, 170, 250, "안전", "-", "한 왕조는 이대로 끝나는 것인가..."); $gencount++;
999, "사마휘",1003, 0, "양양", 71, 11, 96, 0, 173, 234, "은둔", "신산", "좋지, 좋아~"); $gencount++;
999, "우길",1004, 0, "업", 17, 13, 83, 0, 131, 200, "은둔", "신산"); $gencount++;
999, "화타",1005, 0, "낙양", 53, 25, 70, 0, 151, 220, "은둔", "의술", "아픈 사람들은 모두 내게 오시오. 껄껄껄."); $gencount++;
999, "길평",1006, 0, "허창", 27, 15, 72, 0, 158, 200, "은둔", "의술"); $gencount++;
29, "가규",1007, 0, "낙양", 55, 55, 74, 0, 177, 231, "재간", "-"); $gencount++;
136, "가범",1008, 0, "낙양", 58, 48, 73, 0, 202, 237, "유지", "-"); $gencount++;
49, "가비능",1009, 0, "낙양", 58, 83, 32, 0, 172, 235, "정복", "-"); $gencount++;
31, "가충",1010, 0, "낙양", 50, 25, 87, 0, 217, 282, "출세", "-"); $gencount++;
20, "가후",1011, 0, "낙양", 69, 30, 94, 0, 147, 223, "할거", "귀병"); $gencount++;
73, "간옹",1012, 0, "낙양", 31, 33, 70, 0, 164, 225, "안전", "경작"); $gencount++;
129, "감녕",1013, 0, "낙양", 78, 95, 71, 0, 174, 222, "출세", "무쌍"); $gencount++;
127, "감택",1014, 0, "낙양", 62, 44, 79, 0, 182, 243, "유지", "-"); $gencount++;
60, "강단",1015, 0, "낙양", 41, 73, 43, 0, 168, 230, "재간", "-"); $gencount++;
73, "강유",1016, 0, "낙양", 95, 90, 94, 0, 202, 264, "왕좌", "집중"); $gencount++;
102, "고간",1017, 0, "낙양", 60, 57, 51, 0, 168, 206, "유지", "-"); $gencount++;
27, "고람",1018, 0, "낙양", 72, 67, 59, 0, 159, 201, "출세", "기병"); $gencount++;
69, "고상",1019, 0, "낙양", 41, 40, 38, 0, 194, 252, "재간", "-"); $gencount++;
144, "고순",1020, 0, "낙양", 79, 82, 65, 0, 162, 198, "의협", "기병"); $gencount++;
7, "고승",1021, 0, "낙양", 42, 73, 24, 0, 145, 185, "출세", "-"); $gencount++;
120, "고옹",1022, 0, "낙양", 57, 21, 79, 0, 168, 243, "출세", "-"); $gencount++;
63, "고정",1023, 0, "낙양", 67, 65, 55, 0, 190, 251, "정복", "-"); $gencount++;
53, "고패",1024, 0, "낙양", 53, 56, 28, 0, 170, 212, "유지", "-"); $gencount++;
74, "공도",1025, 0, "낙양", 26, 73, 19, 0, 164, 200, "재간", "-"); $gencount++;
142, "공손강",1026, 0, "낙양", 64, 72, 61, 0, 172, 210, "정복", "-"); $gencount++;
142, "공손공",1027, 0, "낙양", 68, 41, 75, 0, 174, 238, "정복", "-"); $gencount++;
142, "공손도",1028, 0, "낙양", 62, 72, 41, 0, 154, 204, "정복", "기병"); $gencount++;
65, "공손범",1029, 0, "낙양", 61, 67, 61, 0, 158, 199, "출세", "-"); $gencount++;
65, "공손속",1030, 0, "낙양", 60, 76, 41, 0, 176, 199, "정복", "-"); $gencount++;
10, "공손연",1031, 0, "낙양", 74, 79, 64, 0, 205, 238, "패권", "돌격"); $gencount++;
65, "공손월",1032, 0, "낙양", 47, 63, 46, 0, 160, 192, "정복", "-"); $gencount++;
65, "공손찬",1033, 0, "낙양", 61, 87, 67, 0, 152, 199, "패권", "기병"); $gencount++;
43, "공융",1034, 0, "낙양", 63, 48, 85, 0, 153, 208, "왕좌", "경작"); $gencount++;
35, "공주",1035, 0, "낙양", 64, 35, 78, 0, 151, 194, "재간", "-"); $gencount++;
83, "공지",1036, 0, "낙양", 57, 54, 64, 0, 178, 242, "대의", "-"); $gencount++;
26, "곽가",1037, 0, "낙양", 47, 23, 99, 0, 170, 207, "패권", "귀모"); $gencount++;
111, "곽도",1038, 0, "낙양", 63, 67, 81, 0, 155, 205, "재간", "-"); $gencount++;
2, "곽사",1039, 0, "낙양", 58, 67, 31, 0, 146, 197, "패권", "-"); $gencount++;
80, "곽유지",1040, 0, "낙양", 37, 22, 71, 0, 190, 259, "재간", "상재"); $gencount++;
67, "곽익",1041, 0, "낙양", 67, 60, 67, 0, 207, 270, "재간", "-"); $gencount++;
67, "곽준",1042, 0, "낙양", 76, 69, 73, 0, 178, 217, "출세", "-"); $gencount++;
27, "곽혁",1043, 0, "낙양", 40, 29, 80, 0, 187, 228, "안전", "-"); $gencount++;
20, "곽회",1044, 0, "낙양", 77, 75, 71, 0, 187, 255, "정복", "-"); $gencount++;
39, "관구검",1045, 0, "낙양", 72, 68, 77, 0, 202, 255, "대의", "-"); $gencount++;
76, "관색",1046, 0, "낙양", 69, 85, 67, 0, 200, 239, "의협", "징병"); $gencount++;
76, "관우",1047, 0, "낙양", 96, 98, 80, 0, 162, 219, "의협", "위압"); $gencount++;
76, "관이",1048, 0, "낙양", 48, 60, 58, 0, 219, 263, "안전", "-"); $gencount++;
76, "관통",1049, 0, "낙양", 49, 63, 60, 0, 218, 259, "대의", "-"); $gencount++;
76, "관평",1050, 0, "낙양", 77, 80, 70, 0, 186, 219, "의협", "보병"); $gencount++;
7, "관해",1051, 0, "낙양", 66, 90, 35, 0, 160, 193, "출세", "-"); $gencount++;
76, "관흥",1052, 0, "낙양", 69, 84, 72, 0, 199, 234, "의협", "돌격"); $gencount++;
40, "괴량",1053, 0, "낙양", 41, 28, 81, 0, 155, 204, "안전", "신중"); $gencount++;
40, "괴월",1054, 0, "낙양", 26, 30, 84, 0, 157, 214, "유지", "귀병"); $gencount++;
98, "교모",1055, 0, "낙양", 59, 58, 61, 0, 150, 191, "안전", "-"); $gencount++;
98, "교현",1056, 0, "낙양", 50, 18, 60, 0, 158, 210, "재간", "-"); $gencount++;
6, "구역거",1057, 0, "낙양", 51, 72, 49, 0, 152, 193, "안전", "-"); $gencount++;
80, "극정",1058, 0, "낙양", 38, 25, 75, 0, 208, 278, "유지", "-"); $gencount++;
46, "금선",1059, 0, "낙양", 55, 49, 36, 0, 155, 208, "할거", "-"); $gencount++;
62, "금환삼결",1060, 0, "낙양", 46, 76, 17, 0, 192, 225, "출세", "-"); $gencount++;
141, "기령",1061, 0, "낙양", 76, 81, 33, 0, 155, 199, "대의", "무쌍"); $gencount++;
122, "낙통",1062, 0, "낙양", 57, 44, 69, 0, 193, 228, "유지", "-"); $gencount++;
124, "노숙1",1063, 0, "낙양", 90, 42, 94, 0, 172, 217, "왕좌", "상재"); $gencount++;
75, "노식",1064, 0, "낙양", 91, 54, 80, 0, 139, 192, "왕좌", "징병"); $gencount++;
59, "뇌동",1065, 0, "낙양", 70, 77, 45, 0, 172, 218, "출세", "궁병"); $gencount++;
142, "뇌박",1066, 0, "낙양", 54, 54, 33, 0, 157, 206, "유지", "-"); $gencount++;
127, "능조",1067, 0, "낙양", 67, 80, 44, 0, 165, 203, "재간", "공성"); $gencount++;
127, "능통",1068, 0, "낙양", 71, 78, 58, 0, 189, 237, "의협", "궁병"); $gencount++;
64, "단경",1069, 0, "낙양", 68, 61, 68, 0, 156, 199, "정복", "-"); $gencount++;
132, "담웅",1070, 0, "낙양", 52, 77, 19, 0, 188, 221, "출세", "-"); $gencount++;
99, "답둔",1071, 0, "낙양", 59, 71, 31, 0, 158, 207, "유지", "-"); $gencount++;
132, "당자",1072, 0, "낙양", 59, 56, 45, 0, 196, 265, "안전", "-"); $gencount++;
60, "대래동주",1073, 0, "낙양", 40, 65, 24, 0, 195, 249, "안전", "-"); $gencount++;
82, "도겸",1074, 0, "낙양", 51, 32, 61, 0, 132, 194, "할거", "인덕"); $gencount++;
120, "도준",1075, 0, "낙양", 64, 57, 50, 0, 238, 285, "안전", "-"); $gencount++;
73, "동궐",1076, 0, "낙양", 66, 50, 76, 0, 204, 271, "대의", "-"); $gencount++;
62, "동다나",1077, 0, "낙양", 51, 71, 27, 0, 189, 225, "유지", "-"); $gencount++;
2, "동민",1078, 0, "낙양", 52, 65, 49, 0, 149, 192, "안전", "-"); $gencount++;
21, "동소",1079, 0, "낙양", 46, 46, 62, 0, 156, 236, "패권", "-"); $gencount++;
127, "동습",1080, 0, "낙양", 53, 64, 32, 0, 169, 215, "출세", "-"); $gencount++;
89, "동승",1081, 0, "낙양", 75, 66, 65, 0, 154, 200, "왕좌", "-"); $gencount++;
78, "동윤",1082, 0, "낙양", 64, 26, 78, 0, 192, 246, "왕좌", "-"); $gencount++;
2, "동탁",1083, 0, "낙양", 87, 91, 54, 0, 139, 192, "패권", "기병"); $gencount++;
66, "동화",1084, 0, "낙양", 48, 64, 53, 0, 168, 219, "대의", "-"); $gencount++;
32, "두예",1085, 0, "낙양", 88, 80, 84, 0, 222, 284, "정복", "-"); $gencount++;
7, "등무",1086, 0, "낙양", 43, 74, 19, 0, 147, 185, "정복", "-"); $gencount++;
41, "등애",1087, 0, "낙양", 94, 82, 92, 0, 197, 264, "패권", "신산"); $gencount++;
116, "등윤",1088, 0, "낙양", 34, 42, 68, 0, 194, 256, "안전", "-"); $gencount++;
73, "등지",1089, 0, "낙양", 74, 51, 80, 0, 182, 251, "할거", "경작"); $gencount++;
41, "등충",1090, 0, "낙양", 60, 82, 55, 0, 230, 264, "출세", "-"); $gencount++;
54, "등현",1091, 0, "낙양", 65, 59, 61, 0, 188, 248, "출세", "-"); $gencount++;
29, "마균",1092, 0, "낙양", 33, 38, 80, 0, 200, 259, "안전", "-"); $gencount++;
71, "마대",1093, 0, "낙양", 77, 79, 49, 0, 183, 246, "대의", "기병"); $gencount++;
70, "마등",1094, 0, "낙양", 80, 87, 56, 0, 149, 211, "왕좌", "기병"); $gencount++;
80, "마속",1095, 0, "낙양", 73, 64, 82, 0, 190, 228, "패권", "집중"); $gencount++;
77, "마량",1096, 0, "낙양", 57, 25, 87, 0, 187, 225, "왕좌", "-"); $gencount++;
48, "마완",1097, 0, "낙양", 49, 64, 26, 0, 170, 211, "안전", "기병"); $gencount++;
19, "마준",1098, 0, "낙양", 45, 63, 62, 0, 196, 260, "안전", "-"); $gencount++;
71, "마철",1099, 0, "낙양", 71, 60, 31, 0, 179, 211, "대의", "기병"); $gencount++;
70, "마초",1100, 0, "낙양", 78, 97, 40, 0, 176, 226, "대의", "기병"); $gencount++;
131, "마충1",1101, 0, "낙양", 67, 62, 51, 0, 186, 222, "재간", "-"); $gencount++;
69, "마충2",1102, 0, "낙양", 61, 68, 51, 0, 187, 249, "출세", "-"); $gencount++;
71, "마휴",1103, 0, "낙양", 71, 60, 32, 0, 178, 211, "대의", "기병"); $gencount++;
116, "만총",1104, 0, "낙양", 79, 40, 78, 0, 170, 242, "할거", "신중"); $gencount++;
51, "망아장",1105, 0, "낙양", 29, 64, 20, 0, 191, 225, "출세", "-"); $gencount++;
44, "맹달",1106, 0, "낙양", 70, 66, 72, 0, 172, 228, "할거", "귀병"); $gencount++;
60, "맹우",1107, 0, "낙양", 63, 79, 26, 0, 190, 251, "정복", "-"); $gencount++;
60, "맹획",1108, 0, "낙양", 78, 92, 50, 0, 186, 245, "왕좌", "격노"); $gencount++;
29, "모개",1109, 0, "낙양", 46, 56, 56, 0, 161, 216, "대의", "-"); $gencount++;
51, "목록대왕",1110, 0, "낙양", 58, 71, 65, 0, 184, 225, "재간", "척사"); $gencount++;
96, "목순",1111, 0, "낙양", 17, 21, 68, 0, 157, 191, "왕좌", "-"); $gencount++;
43, "무안국",1112, 0, "낙양", 51, 73, 18, 0, 156, 191, "재간", "-"); $gencount++;
28, "문빙",1113, 0, "낙양", 70, 77, 43, 0, 178, 237, "유지", "-"); $gencount++;
38, "문앙",1114, 0, "낙양", 71, 91, 46, 0, 222, 285, "대의", "-"); $gencount++;
102, "문추",1115, 0, "낙양", 72, 94, 25, 0, 161, 200, "출세", "무쌍"); $gencount++;
38, "문흠",1116, 0, "낙양", 76, 77, 43, 0, 200, 258, "대의", "-"); $gencount++;
49, "미당대왕",1117, 0, "낙양", 64, 75, 32, 0, 202, 260, "유지", "-"); $gencount++;
108, "미방",1118, 0, "낙양", 58, 65, 37, 0, 169, 222, "패권", "징병"); $gencount++;
77, "미축",1119, 0, "낙양", 26, 30, 65, 0, 165, 220, "왕좌", "상재"); $gencount++;
94, "반봉",1120, 0, "낙양", 61, 75, 17, 0, 155, 191, "출세", "-"); $gencount++;
44, "반준",1121, 0, "낙양", 41, 21, 67, 0, 174, 239, "안전", "-"); $gencount++;
65, "방덕",1122, 0, "낙양", 76, 90, 67, 0, 170, 219, "의협", "기병"); $gencount++;
73, "방통",1123, 0, "낙양", 86, 41, 97, 0, 179, 214, "패권", "반계"); $gencount++;
65, "방회",1124, 0, "낙양", 25, 33, 59, 0, 205, 272, "안전", "-"); $gencount++;
68, "배원소",1125, 0, "낙양", 45, 69, 33, 0, 169, 200, "재간", "-"); $gencount++;
78, "번건",1126, 0, "낙양", 28, 31, 68, 0, 205, 270, "대의", "-"); $gencount++;
149, "번주",1127, 0, "낙양", 67, 77, 21, 0, 149, 192, "할거", "-"); $gencount++;
72, "법정",1128, 0, "낙양", 81, 29, 93, 0, 176, 220, "패권", "신산"); $gencount++;
8, "변희",1129, 0, "낙양", 65, 65, 27, 0, 169, 200, "안전", "-"); $gencount++;
121, "보질",1130, 0, "낙양", 58, 28, 77, 0, 177, 247, "유지", "-"); $gencount++;
113, "복양흥",1131, 0, "낙양", 58, 51, 71, 0, 224, 264, "유지", "-"); $gencount++;
110, "봉기",1132, 0, "낙양", 68, 52, 80, 0, 153, 202, "패권", "집중"); $gencount++;
74, "부동",1133, 0, "낙양", 58, 69, 69, 0, 183, 222, "대의", "-"); $gencount++;
108, "부사인",1134, 0, "낙양", 54, 59, 51, 0, 182, 222, "출세", "-"); $gencount++;
38, "부손",1135, 0, "낙양", 24, 43, 68, 0, 162, 230, "안전", "-"); $gencount++;
74, "부첨",1136, 0, "낙양", 61, 74, 45, 0, 216, 263, "대의", "-"); $gencount++;
66, "비시",1137, 0, "낙양", 18, 36, 61, 0, 176, 240, "재간", "-"); $gencount++;
141, "비연",1138, 0, "낙양", 66, 65, 53, 0, 196, 238, "출세", "-"); $gencount++;
77, "비위",1139, 0, "낙양", 72, 26, 73, 0, 193, 253, "대의", "-"); $gencount++;
144, "사광",1140, 0, "낙양", 57, 49, 66, 0, 175, 235, "안전", "-"); $gencount++;
71, "사마가",1141, 0, "낙양", 61, 85, 18, 0, 167, 222, "정복", "돌격"); $gencount++;
20, "사마랑",1142, 0, "낙양", 25, 32, 63, 0, 171, 217, "대의", "-"); $gencount++;
24, "사마망",1143, 0, "낙양", 71, 61, 65, 0, 205, 271, "정복", "-"); $gencount++;
24, "사마부",1144, 0, "낙양", 55, 31, 73, 0, 180, 272, "대의", "-"); $gencount++;
31, "사마사",1145, 0, "낙양", 87, 64, 91, 0, 208, 255, "정복", "-"); $gencount++;
31, "사마소",1146, 0, "낙양", 93, 63, 84, 0, 211, 265, "정복", "-"); $gencount++;
31, "사마염",1147, 0, "낙양", 92, 78, 72, 0, 236, 290, "패권", "-"); $gencount++;
30, "사마유",1148, 0, "낙양", 62, 45, 79, 0, 248, 283, "왕좌", "-"); $gencount++;
31, "사마의",1149, 0, "낙양", 98, 67, 98, 0, 179, 251, "패권", "반계"); $gencount++;
139, "사섭",1150, 0, "낙양", 63, 61, 71, 0, 137, 226, "안전", "-"); $gencount++;
139, "사일",1151, 0, "낙양", 59, 44, 68, 0, 153, 230, "유지", "-"); $gencount++;
132, "사정",1152, 0, "낙양", 67, 71, 20, 0, 178, 221, "안전", "-"); $gencount++;
146, "사지",1153, 0, "낙양", 61, 49, 70, 0, 163, 227, "안전", "-"); $gencount++;
144, "사휘",1154, 0, "낙양", 67, 71, 61, 0, 165, 227, "유지", "-"); $gencount++;
35, "서막",1155, 0, "낙양", 56, 41, 72, 0, 171, 249, "유지", "-"); $gencount++;
76, "서서",1156, 0, "낙양", 90, 70, 96, 0, 178, 232, "의협", "귀병"); $gencount++;
124, "서성",1157, 0, "낙양", 83, 76, 83, 0, 177, 234, "대의", "-"); $gencount++;
142, "서영",1158, 0, "낙양", 47, 63, 33, 0, 147, 191, "안전", "-"); $gencount++;
23, "서질",1159, 0, "낙양", 55, 73, 34, 0, 207, 253, "재간", "-"); $gencount++;
23, "서황",1160, 0, "낙양", 79, 89, 68, 0, 165, 228, "의협", "필살"); $gencount++;
32, "석포",1161, 0, "낙양", 71, 63, 59, 0, 214, 272, "정복", "-"); $gencount++;
131, "설영",1162, 0, "낙양", 46, 23, 64, 0, 223, 282, "유지", "-"); $gencount++;
128, "설종",1163, 0, "낙양", 27, 33, 67, 0, 187, 243, "유지", "-"); $gencount++;
69, "성의",1164, 0, "낙양", 45, 64, 22, 0, 168, 211, "재간", "-"); $gencount++;
129, "소비",1165, 0, "낙양", 67, 63, 49, 0, 172, 221, "대의", "-"); $gencount++;
76, "손건",1166, 0, "낙양", 42, 33, 73, 0, 165, 215, "대의", null); $gencount++;
125, "손견",1167, 0, "낙양", 96, 95, 76, 0, 156, 192, "왕좌", "무쌍"); $gencount++;
126, "손광",1168, 0, "낙양", 63, 54, 58, 0, 186, 207, "유지", "-"); $gencount++;
125, "손권",1169, 0, "낙양", 90, 77, 83, 0, 182, 252, "할거", "수비"); $gencount++;
126, "손랑",1170, 0, "낙양", 27, 54, 28, 0, 187, 226, "안전", "-"); $gencount++;
126, "손등",1171, 0, "낙양", 52, 39, 77, 0, 209, 241, "할거", "-"); $gencount++;
125, "손량",1172, 0, "낙양", 24, 23, 79, 0, 243, 260, "할거", "-"); $gencount++;
20, "손례",1173, 0, "낙양", 64, 64, 69, 0, 180, 250, "안전", "-"); $gencount++;
124, "손소",1174, 0, "낙양", 76, 80, 68, 0, 188, 241, "정복", "-"); $gencount++;
130, "손수",1175, 0, "낙양", 67, 57, 59, 0, 235, 299, "안전", "-"); $gencount++;
126, "손유",1176, 0, "낙양", 77, 60, 67, 0, 177, 215, "정복", "-"); $gencount++;
122, "손이",1177, 0, "낙양", 57, 62, 57, 0, 223, 272, "안전", "-"); $gencount++;
126, "손정",1178, 0, "낙양", 59, 56, 62, 0, 160, 206, "유지", "-"); $gencount++;
115, "손준",1179, 0, "낙양", 59, 69, 51, 0, 219, 256, "정복", "-"); $gencount++;
7, "손중",1180, 0, "낙양", 53, 63, 24, 0, 154, 185, "안전", "-"); $gencount++;
125, "손책",1181, 0, "낙양", 96, 96, 78, 0, 175, 200, "패권", "필살"); $gencount++;
115, "손침",1182, 0, "낙양", 49, 71, 40, 0, 231, 258, "패권", "-"); $gencount++;
114, "손호",1183, 0, "낙양", 20, 78, 67, 0, 242, 284, "패권", "-"); $gencount++;
126, "손화",1184, 0, "낙양", 35, 25, 71, 0, 224, 253, "왕좌", "-"); $gencount++;
127, "손환",1185, 0, "낙양", 79, 65, 70, 0, 197, 228, "정복", "-"); $gencount++;
126, "손휴",1186, 0, "낙양", 63, 43, 64, 0, 235, 264, "정복", "-"); $gencount++;
117, "손흠",1187, 0, "낙양", 66, 63, 33, 0, 235, 280, "정복", "-"); $gencount++;
147, "송헌",1188, 0, "낙양", 42, 63, 41, 0, 157, 200, "안전", "-"); $gencount++;
95, "순우경",1189, 0, "낙양", 72, 67, 60, 0, 146, 200, "할거", "-"); $gencount++;
22, "순욱1",1190, 0, "낙양", 54, 29, 97, 0, 163, 212, "왕좌", "집중"); $gencount++;
22, "순유",1191, 0, "낙양", 73, 41, 90, 0, 157, 214, "대의", "신중"); $gencount++;
29, "신비",1192, 0, "낙양", 47, 28, 74, 0, 171, 240, "재간", "-"); $gencount++;
37, "신의",1193, 0, "낙양", 55, 61, 51, 0, 190, 252, "출세", "-"); $gencount++;
37, "신탐",1194, 0, "낙양", 56, 58, 57, 0, 188, 254, "출세", "-"); $gencount++;
85, "신평",1195, 0, "낙양", 68, 51, 75, 0, 165, 204, "왕좌", "-"); $gencount++;
102, "심배",1196, 0, "낙양", 75, 66, 68, 0, 156, 204, "패권", "귀병"); $gencount++;
126, "심영",1197, 0, "낙양", 53, 72, 51, 0, 235, 280, "재간", "-"); $gencount++;
47, "아하소과",1198, 0, "낙양", 53, 75, 15, 0, 204, 253, "안전", "척사"); $gencount++;
62, "아회남",1199, 0, "낙양", 50, 74, 30, 0, 190, 225, "출세", "척사"); $gencount++;
23, "악진",1200, 0, "낙양", 73, 67, 56, 0, 159, 218, "대의", "돌격"); $gencount++;
23, "악침",1201, 0, "낙양", 45, 52, 33, 0, 196, 257, "대의", "-"); $gencount++;
63, "악환",1202, 0, "낙양", 54, 82, 55, 0, 196, 251, "재간", "-"); $gencount++;
102, "안량",1203, 0, "낙양", 73, 93, 36, 0, 160, 200, "출세", "위압"); $gencount++;
14, "양백",1204, 0, "낙양", 55, 54, 53, 0, 171, 214, "안전", "-"); $gencount++;
92, "양봉1",1205, 0, "낙양", 57, 64, 36, 0, 153, 197, "유지", "-"); $gencount++;
91, "양봉2",1206, 0, "낙양", 62, 78, 61, 0, 191, 252, "정복", "-"); $gencount++;
13, "양송",1207, 0, "낙양", 15, 35, 34, 0, 167, 215, "안전", "-"); $gencount++;
43, "양수",1208, 0, "낙양", 18, 31, 91, 0, 175, 219, "재간", "귀병"); $gencount++;
61, "양의",1209, 0, "낙양", 67, 56, 71, 0, 190, 235, "유지", "-"); $gencount++;
141, "양조1",1210, 0, "낙양", 68, 54, 60, 0, 202, 256, "출세", "-"); $gencount++;
9, "양추1",1211, 0, "낙양", 51, 67, 16, 0, 159, 199, "정복", "-"); $gencount++;
31, "양호",1212, 0, "낙양", 91, 69, 80, 0, 221, 278, "패권", "-"); $gencount++;
53, "양회",1213, 0, "낙양", 60, 67, 40, 0, 167, 212, "출세", "-"); $gencount++;
141, "양흥",1214, 0, "낙양", 52, 68, 17, 0, 169, 211, "안전", "-"); $gencount++;
6, "어부라",1215, 0, "낙양", 78, 80, 61, 0, 150, 195, "정복", "-"); $gencount++;
64, "엄강",1216, 0, "낙양", 57, 65, 44, 0, 163, 192, "재간", "-"); $gencount++;
10, "엄백호",1217, 0, "낙양", 48, 68, 30, 0, 150, 197, "할거", "-"); $gencount++;
10, "엄여",1218, 0, "낙양", 35, 66, 24, 0, 153, 197, "할거", "-"); $gencount++;
69, "엄안",1219, 0, "낙양", 72, 84, 67, 0, 151, 222, "왕좌", "-"); $gencount++;
7, "엄정",1220, 0, "낙양", 31, 68, 49, 0, 151, 189, "출세", "-"); $gencount++;
121, "엄준",1221, 0, "낙양", 44, 24, 71, 0, 169, 246, "재간", "-"); $gencount++;
71, "여개",1222, 0, "낙양", 51, 42, 67, 0, 194, 227, "유지", "-"); $gencount++;
29, "여건",1223, 0, "낙양", 44, 68, 29, 0, 173, 238, "출세", "-"); $gencount++;
107, "여광",1224, 0, "낙양", 60, 67, 27, 0, 162, 207, "유지", "-"); $gencount++;
124, "여몽",1225, 0, "낙양", 92, 78, 93, 0, 178, 219, "패권", "궁병"); $gencount++;
123, "여범",1226, 0, "낙양", 43, 34, 71, 0, 169, 228, "할거", "-"); $gencount++;
107, "여상",1227, 0, "낙양", 62, 68, 26, 0, 164, 207, "유지", "-"); $gencount++;
105, "여위황",1228, 0, "낙양", 42, 62, 38, 0, 159, 200, "정복", "-"); $gencount++;
145, "여포",1229, 0, "낙양", 74,100, 29, 0, 156, 198, "패권", "돌격"); $gencount++;
50, "염우",1230, 0, "낙양", 58, 51, 18, 0, 209, 264, "출세", "-"); $gencount++;
40, "염유",1231, 0, "낙양", 59, 75, 51, 0, 168, 227, "출세", "-"); $gencount++;
18, "염포",1232, 0, "낙양", 33, 35, 77, 0, 163, 231, "유지", "-"); $gencount++;
40, "예형",1233, 0, "낙양", 77, 31, 95, 0, 173, 209, "은둔", "통찰"); $gencount++;
133, "오강",1234, 0, "낙양", 47, 37, 61, 0, 216, 275, "안전", "-"); $gencount++;
59, "오란",1235, 0, "낙양", 67, 75, 42, 0, 170, 218, "재간", "-"); $gencount++;
72, "오반",1236, 0, "낙양", 70, 66, 45, 0, 171, 234, "재간", "-"); $gencount++;
128, "오언",1237, 0, "낙양", 71, 60, 52, 0, 235, 297, "재간", "-"); $gencount++;
126, "오연",1238, 0, "낙양", 36, 70, 31, 0, 234, 280, "정복", "-"); $gencount++;
69, "오의",1239, 0, "낙양", 75, 72, 74, 0, 165, 237, "유지", "-"); $gencount++;
19, "오질",1240, 0, "낙양", 43, 37, 69, 0, 177, 230, "출세", "-"); $gencount++;
51, "올돌골",1241, 0, "낙양", 77, 92, 15, 0, 186, 225, "출세", "척사"); $gencount++;
52, "옹개",1242, 0, "낙양", 58, 67, 51, 0, 188, 225, "안전", "-"); $gencount++;
20, "왕경",1243, 0, "낙양", 55, 47, 65, 0, 206, 260, "재간", "-"); $gencount++;
97, "왕광",1244, 0, "낙양", 72, 67, 54, 0, 150, 190, "유지", "-"); $gencount++;
30, "왕기1",1245, 0, "낙양", 76, 62, 70, 0, 190, 261, "유지", "-"); $gencount++;
34, "왕랑",1246, 0, "낙양", 49, 29, 51, 0, 162, 228, "할거", "-"); $gencount++;
57, "왕루",1247, 0, "낙양", 40, 28, 76, 0, 173, 211, "유지", "-"); $gencount++;
76, "왕보",1248, 0, "낙양", 47, 34, 75, 0, 171, 219, "대의", "-"); $gencount++;
86, "왕수",1249, 0, "낙양", 34, 34, 67, 0, 168, 218, "재간", "-"); $gencount++;
26, "왕쌍",1250, 0, "낙양", 58, 89, 15, 0, 195, 228, "정복", "보병"); $gencount++;
46, "왕위",1251, 0, "낙양", 59, 60, 68, 0, 163, 208, "안전", "-"); $gencount++;
92, "왕윤",1252, 0, "낙양", 16, 18, 77, 0, 137, 192, "왕좌", "-"); $gencount++;
40, "왕융",1253, 0, "낙양", 62, 41, 77, 0, 234, 305, "재간", "-"); $gencount++;
32, "왕준",1254, 0, "낙양", 81, 83, 76, 0, 206, 285, "대의", "-"); $gencount++;
30, "왕찬",1255, 0, "낙양", 28, 28, 78, 0, 177, 217, "안전", "-"); $gencount++;
33, "왕창",1256, 0, "낙양", 74, 57, 52, 0, 188, 259, "정복", "-"); $gencount++;
69, "왕평",1257, 0, "낙양", 77, 76, 71, 0, 192, 248, "재간", "-"); $gencount++;
71, "왕항",1258, 0, "낙양", 51, 43, 60, 0, 184, 254, "대의", "-"); $gencount++;
33, "왕혼",1259, 0, "낙양", 69, 32, 59, 0, 223, 297, "정복", "-"); $gencount++;
71, "요립",1260, 0, "낙양", 65, 41, 84, 0, 181, 250, "출세", "-"); $gencount++;
74, "요화",1261, 0, "낙양", 67, 58, 60, 0, 170, 264, "의협", "-"); $gencount++;
22, "우금1",1262, 0, "낙양", 80, 74, 71, 0, 159, 221, "정복", "-"); $gencount++;
27, "우금2",1263, 0, "낙양", 63, 77, 37, 0, 173, 226, "대의", "-"); $gencount++;
122, "우번",1264, 0, "낙양", 23, 42, 73, 0, 164, 233, "유지", "-"); $gencount++;
126, "우전",1265, 0, "낙양", 63, 55, 41, 0, 204, 258, "안전", "-"); $gencount++;
86, "원담",1266, 0, "낙양", 67, 59, 55, 0, 173, 205, "왕좌", "-"); $gencount++;
101, "원상",1267, 0, "낙양", 54, 72, 68, 0, 179, 207, "패권", "-"); $gencount++;
101, "원소",1268, 0, "낙양", 85, 67, 76, 0, 154, 202, "패권", "위압"); $gencount++;
140, "원술",1269, 0, "낙양", 77, 59, 71, 0, 155, 199, "패권", "축성"); $gencount++;
140, "원윤",1270, 0, "낙양", 41, 34, 60, 0, 163, 199, "패권", "-"); $gencount++;
101, "원희",1271, 0, "낙양", 69, 57, 72, 0, 176, 207, "할거", "-"); $gencount++;
131, "위소",1272, 0, "낙양", 39, 24, 82, 0, 204, 273, "재간", "-"); $gencount++;
147, "위속",1273, 0, "낙양", 57, 59, 41, 0, 156, 200, "안전", "-"); $gencount++;
81, "위연",1274, 0, "낙양", 78, 94, 62, 0, 175, 234, "패권", "보병"); $gencount++;
96, "위유",1275, 0, "낙양", 53, 69, 71, 0, 151, 193, "재간", "-"); $gencount++;
76, "유기",1276, 0, "낙양", 57, 19, 73, 0, 174, 209, "왕좌", "-"); $gencount++;
36, "유대",1277, 0, "낙양", 61, 57, 62, 0, 147, 202, "재간", "-"); $gencount++;
134, "유도",1278, 0, "낙양", 35, 33, 68, 0, 168, 214, "재간", "-"); $gencount++;
46, "유벽",1279, 0, "낙양", 63, 71, 23, 0, 168, 210, "출세", "-"); $gencount++;
75, "유봉",1280, 0, "낙양", 60, 65, 62, 0, 188, 220, "출세", "-"); $gencount++;
75, "유비",1281, 0, "낙양", 85, 75, 70, 0, 161, 223, "왕좌", "인덕"); $gencount++;
75, "유선1",1282, 0, "낙양", 24, 17, 21, 0, 207, 271, "대의", "-"); $gencount++;
55, "유순",1283, 0, "낙양", 67, 61, 54, 0, 184, 239, "출세", "-"); $gencount++;
75, "유심",1284, 0, "낙양", 63, 46, 70, 0, 238, 263, "왕좌", "-"); $gencount++;
129, "유약",1285, 0, "낙양", 67, 63, 61, 0, 206, 260, "유지", "-"); $gencount++;
55, "유언",1286, 0, "낙양", 60, 40, 74, 0, 132, 194, "할거", "-"); $gencount++;
27, "유엽",1287, 0, "낙양", 40, 29, 79, 0, 176, 235, "유지", "-"); $gencount++;
11, "유요",1288, 0, "낙양", 23, 22, 48, 0, 156, 195, "안전", "발명"); $gencount++;
96, "유우",1289, 0, "낙양", 68, 34, 72, 0, 145, 193, "왕좌", "-"); $gencount++;
55, "유장",1290, 0, "낙양", 38, 31, 63, 0, 162, 219, "할거", "수비"); $gencount++;
45, "유종",1291, 0, "낙양", 22, 26, 61, 0, 191, 208, "할거", "-"); $gencount++;
56, "유파",1292, 0, "낙양", 47, 32, 70, 0, 186, 222, "대의", "-"); $gencount++;
45, "유표1",1293, 0, "낙양", 71, 57, 71, 0, 142, 208, "할거", "-"); $gencount++;
27, "유표2",1294, 0, "낙양", 76, 55, 71, 0, 173, 229, "안전", "-"); $gencount++;
134, "유현",1295, 0, "낙양", 32, 56, 55, 0, 188, 252, "안전", "-"); $gencount++;
122, "육개",1296, 0, "낙양", 66, 30, 72, 0, 198, 269, "재간", "-"); $gencount++;
122, "육손",1297, 0, "낙양", 98, 68, 98, 0, 183, 245, "왕좌", "귀병"); $gencount++;
121, "육적",1298, 0, "낙양", 44, 29, 73, 0, 187, 219, "안전", "-"); $gencount++;
122, "육항",1299, 0, "낙양", 95, 69, 94, 0, 226, 274, "왕좌", "-"); $gencount++;
38, "윤대목",1300, 0, "낙양", 62, 49, 69, 0, 211, 270, "재간", "-"); $gencount++;
80, "윤묵",1301, 0, "낙양", 19, 28, 73, 0, 183, 239, "대의", "-"); $gencount++;
72, "윤상",1302, 0, "낙양", 30, 32, 42, 0, 194, 260, "대의", "-"); $gencount++;
136, "윤직",1303, 0, "낙양", 44, 58, 63, 0, 197, 237, "재간", "-"); $gencount++;
2, "이각",1304, 0, "낙양", 56, 77, 43, 0, 148, 198, "패권", "-"); $gencount++;
146, "이숙",1305, 0, "낙양", 27, 45, 67, 0, 156, 192, "재간", "-"); $gencount++;
71, "이엄",1306, 0, "낙양", 80, 84, 81, 0, 172, 234, "패권", "-"); $gencount++;
2, "이유",1307, 0, "낙양", 64, 22, 90, 0, 150, 192, "패권", "귀모"); $gencount++;
132, "이이",1308, 0, "낙양", 55, 75, 20, 0, 187, 222, "정복", "-"); $gencount++;
77, "이적",1309, 0, "낙양", 55, 27, 77, 0, 162, 226, "할거", "-"); $gencount++;
22, "이전",1310, 0, "낙양", 75, 68, 82, 0, 174, 216, "왕좌", "-"); $gencount++;
71, "이풍1",1311, 0, "낙양", 59, 56, 62, 0, 206, 260, "재간", "-"); $gencount++;
66, "이회",1312, 0, "낙양", 67, 50, 79, 0, 175, 231, "유지", "-"); $gencount++;
114, "잠혼",1313, 0, "낙양", 15, 16, 44, 0, 239, 280, "할거", "-"); $gencount++;
7, "장각",1314, 0, "낙양", 93, 25, 93, 0, 140, 185, "패권", "환술"); $gencount++;
34, "장간",1315, 0, "낙양", 19, 20, 70, 0, 175, 239, "재간", "-"); $gencount++;
7, "장개",1316, 0, "낙양", 48, 69, 19, 0, 155, 202, "안전", "-"); $gencount++;
122, "장굉",1317, 0, "낙양", 25, 21, 85, 0, 153, 212, "왕좌", "-"); $gencount++;
7, "장량",1318, 0, "낙양", 68, 81, 68, 0, 153, 185, "정복", "환술"); $gencount++;
15, "장로",1319, 0, "낙양", 76, 44, 80, 0, 163, 237, "유지", "축성"); $gencount++;
23, "장료",1320, 0, "낙양", 89, 93, 83, 0, 169, 222, "의협", "견고"); $gencount++;
7, "장보",1321, 0, "낙양", 78, 81, 76, 0, 148, 185, "패권", "환술"); $gencount++;
76, "장비",1322, 0, "낙양", 79, 99, 48, 0, 167, 221, "의협", "무쌍"); $gencount++;
62, "장서",1323, 0, "낙양", 44, 48, 35, 0, 225, 290, "출세", "-"); $gencount++;
120, "장소1",1324, 0, "낙양", 42, 24, 91, 0, 156, 236, "안전", "-"); $gencount++;
78, "장소2",1325, 0, "낙양", 51, 44, 71, 0, 202, 264, "재간", "-"); $gencount++;
72, "장송",1326, 0, "낙양", 49, 28, 93, 0, 170, 212, "할거", "통찰"); $gencount++;
148, "장수",1327, 0, "낙양", 71, 72, 69, 0, 154, 207, "할거", "-"); $gencount++;
145, "장양1",1328, 0, "낙양", 62, 66, 65, 0, 150, 199, "출세", "-"); $gencount++;
8, "장연",1329, 0, "낙양", 78, 66, 47, 0, 153, 210, "안전", "-"); $gencount++;
11, "장영",1330, 0, "낙양", 55, 65, 40, 0, 154, 195, "재간", "-"); $gencount++;
118, "장온",1331, 0, "낙양", 21, 30, 69, 0, 193, 231, "할거", "-"); $gencount++;
78, "장완",1332, 0, "낙양", 70, 55, 86, 0, 188, 246, "할거", "상재"); $gencount++;
15, "장위",1333, 0, "낙양", 65, 70, 29, 0, 172, 215, "대의", "-"); $gencount++;
36, "장윤",1334, 0, "낙양", 67, 59, 60, 0, 163, 208, "정복", "-"); $gencount++;
104, "장의거",1335, 0, "낙양", 68, 59, 34, 0, 159, 205, "대의", "-"); $gencount++;
68, "장익",1336, 0, "낙양", 75, 68, 63, 0, 188, 264, "유지", "-"); $gencount++;
56, "장임",1337, 0, "낙양", 83, 82, 74, 0, 169, 214, "대의", "견고"); $gencount++;
148, "장제1",1338, 0, "낙양", 70, 65, 59, 0, 144, 196, "할거", "-"); $gencount++;
32, "장제2",1339, 0, "낙양", 30, 33, 84, 0, 188, 249, "유지", "-"); $gencount++;
126, "장제3",1340, 0, "낙양", 74, 49, 61, 0, 236, 280, "할거", "-"); $gencount++;
17, "장패",1341, 0, "낙양", 44, 78, 43, 0, 165, 231, "할거", "-"); $gencount++;
76, "장포1",1342, 0, "낙양", 69, 85, 49, 0, 198, 229, "재간", "징병"); $gencount++;
113, "장포2",1343, 0, "낙양", 63, 66, 51, 0, 225, 264, "유지", "-"); $gencount++;
27, "장합",1344, 0, "낙양", 83, 91, 63, 0, 167, 231, "출세", "궁병"); $gencount++;
23, "장호",1345, 0, "낙양", 56, 62, 54, 0, 195, 240, "정복", "-"); $gencount++;
31, "장화",1346, 0, "낙양", 49, 24, 86, 0, 232, 300, "유지", "-"); $gencount++;
48, "장횡",1347, 0, "낙양", 53, 67, 25, 0, 178, 211, "재간", "-"); $gencount++;
141, "장훈",1348, 0, "낙양", 67, 61, 60, 0, 156, 206, "안전", "-"); $gencount++;
120, "장휴",1349, 0, "낙양", 42, 35, 70, 0, 204, 244, "재간", "-"); $gencount++;
126, "장흠",1350, 0, "낙양", 64, 66, 67, 0, 168, 219, "대의", "저격"); $gencount++;
96, "저수",1351, 0, "낙양", 82, 54, 88, 0, 156, 201, "할거", "반계"); $gencount++;
130, "전단",1352, 0, "낙양", 64, 73, 61, 0, 204, 261, "출세", "-"); $gencount++;
42, "전속",1353, 0, "낙양", 66, 57, 49, 0, 218, 272, "안전", "-"); $gencount++;
26, "전위1",1354, 0, "낙양", 61, 96, 34, 0, 160, 197, "의협", "필살"); $gencount++;
130, "전위2",1355, 0, "낙양", 74, 69, 62, 0, 230, 274, "출세", "-"); $gencount++;
128, "전종",1356, 0, "낙양", 79, 77, 74, 0, 183, 249, "패권", "-"); $gencount++;
42, "전주",1357, 0, "낙양", 69, 67, 51, 0, 169, 214, "의협", "-"); $gencount++;
96, "전풍",1358, 0, "낙양", 81, 41, 96, 0, 162, 200, "왕좌", "-"); $gencount++;
24, "정무",1359, 0, "낙양", 54, 38, 74, 0, 201, 265, "출세", "-"); $gencount++;
119, "정병",1360, 0, "낙양", 22, 25, 67, 0, 172, 226, "유지", "-"); $gencount++;
126, "정보",1361, 0, "낙양", 81, 64, 76, 0, 151, 216, "패권", "-"); $gencount++;
123, "정봉1",1362, 0, "낙양", 70, 77, 64, 0, 190, 271, "패권", "-"); $gencount++;
24, "정욱",1363, 0, "낙양", 80, 39, 90, 0, 141, 220, "패권", "신중"); $gencount++;
88, "정원",1364, 0, "낙양", 64, 77, 58, 0, 137, 190, "왕좌", "기병"); $gencount++;
7, "정원지",1365, 0, "낙양", 41, 74, 38, 0, 145, 185, "출세", "-"); $gencount++;
69, "정은",1366, 0, "낙양", 53, 62, 26, 0, 169, 211, "재간", "-"); $gencount++;
121, "제갈각",1367, 0, "낙양", 61, 53, 92, 0, 203, 253, "왕좌", "-"); $gencount++;
76, "제갈균",1368, 0, "낙양", 59, 45, 74, 0, 185, 252, "안전", "상재"); $gencount++;
121, "제갈근",1369, 0, "낙양", 60, 42, 88, 0, 174, 241, "왕좌", "경작"); $gencount++;
76, "제갈량",1370, 0, "낙양", 97, 55,100, 0, 181, 234, "왕좌", "집중"); $gencount++;
76, "제갈상",1371, 0, "낙양", 52, 75, 71, 0, 246, 263, "대의", "-"); $gencount++;
135, "제갈정",1372, 0, "낙양", 56, 57, 54, 0, 241, 300, "안전", "-"); $gencount++;
76, "제갈첨",1373, 0, "낙양", 73, 52, 76, 0, 227, 263, "대의", "-"); $gencount++;
135, "제갈탄",1374, 0, "낙양", 79, 79, 73, 0, 206, 258, "패권", "-"); $gencount++;
76, "조광",1375, 0, "낙양", 65, 67, 54, 0, 210, 263, "재간", "-"); $gencount++;
74, "조루",1376, 0, "낙양", 49, 37, 60, 0, 183, 219, "대의", "-"); $gencount++;
24, "조모",1377, 0, "낙양", 53, 32, 30, 0, 241, 260, "할거", "-"); $gencount++;
127, "조무",1378, 0, "낙양", 71, 68, 71, 0, 155, 191, "의협", "-"); $gencount++;
26, "조방",1379, 0, "낙양", 50, 20, 31, 0, 232, 274, "정복", "-"); $gencount++;
83, "조범",1380, 0, "낙양", 58, 40, 63, 0, 168, 218, "유지", "-"); $gencount++;
26, "조비",1381, 0, "낙양", 72, 69, 75, 0, 187, 226, "패권", "징병"); $gencount++;
19, "조상",1382, 0, "낙양", 68, 62, 31, 0, 207, 249, "패권", "-"); $gencount++;
147, "조성",1383, 0, "낙양", 44, 69, 51, 0, 163, 198, "안전", "-"); $gencount++;
26, "조순",1384, 0, "낙양", 66, 57, 72, 0, 170, 210, "정복", "-"); $gencount++;
25, "조식",1385, 0, "낙양", 19, 19, 90, 0, 192, 232, "왕좌", "귀모"); $gencount++;
25, "조앙",1386, 0, "낙양", 44, 65, 62, 0, 175, 197, "왕좌", "-"); $gencount++;
25, "조예",1387, 0, "낙양", 57, 55, 82, 0, 205, 239, "정복", "-"); $gencount++;
26, "조우",1388, 0, "낙양", 67, 55, 67, 0, 199, 260, "대의", "-"); $gencount++;
76, "조운",1389, 0, "낙양", 95, 98, 87, 0, 168, 229, "왕좌", "무쌍"); $gencount++;
25, "조웅",1390, 0, "낙양", 59, 27, 44, 0, 194, 220, "안전", "-"); $gencount++;
26, "조인",1391, 0, "낙양", 74, 79, 62, 0, 168, 223, "패권", "보병"); $gencount++;
25, "조조",1392, 0, "낙양",100, 80, 95, 0, 155, 220, "패권", "반계"); $gencount++;
26, "조진",1393, 0, "낙양", 82, 67, 65, 0, 185, 231, "정복", "-"); $gencount++;
25, "조창",1394, 0, "낙양", 75, 88, 37, 0, 190, 223, "정복", "돌격"); $gencount++;
76, "조통",1395, 0, "낙양", 65, 64, 55, 0, 209, 260, "재간", "-"); $gencount++;
84, "조표",1396, 0, "낙양", 34, 70, 16, 0, 151, 196, "안전", "-"); $gencount++;
7, "조홍1",1397, 0, "낙양", 52, 66, 42, 0, 156, 185, "유지", "-"); $gencount++;
24, "조홍2",1398, 0, "낙양", 72, 69, 44, 0, 169, 232, "패권", "-"); $gencount++;
26, "조환",1399, 0, "낙양", 34, 24, 42, 0, 246, 302, "정복", "-"); $gencount++;
19, "조훈",1400, 0, "낙양", 67, 63, 30, 0, 212, 249, "출세", "-"); $gencount++;
26, "조휴",1401, 0, "낙양", 75, 71, 70, 0, 174, 228, "패권", "-"); $gencount++;
19, "조희",1402, 0, "낙양", 64, 57, 71, 0, 210, 249, "대의", "-"); $gencount++;
22, "종요",1403, 0, "낙양", 16, 20, 74, 0, 151, 230, "유지", "-"); $gencount++;
20, "종회",1404, 0, "낙양", 84, 58, 93, 0, 225, 264, "패권", "-"); $gencount++;
128, "주거",1405, 0, "낙양", 73, 71, 72, 0, 190, 246, "유지", "-"); $gencount++;
118, "주방",1406, 0, "낙양", 56, 36, 76, 0, 200, 240, "할거", "-"); $gencount++;
126, "주연",1407, 0, "낙양", 73, 72, 51, 0, 182, 249, "할거", "-"); $gencount++;
126, "주유",1408, 0, "낙양", 97, 73, 97, 0, 175, 210, "패권", "신산"); $gencount++;
128, "주이",1409, 0, "낙양", 61, 55, 61, 0, 201, 257, "안전", "-"); $gencount++;
88, "주준",1410, 0, "낙양", 82, 75, 65, 0, 149, 195, "왕좌", "-"); $gencount++;
32, "주지",1411, 0, "낙양", 52, 77, 47, 0, 233, 295, "안전", "-"); $gencount++;
76, "주창",1412, 0, "낙양", 42, 79, 30, 0, 164, 219, "의협", "궁병"); $gencount++;
126, "주치",1413, 0, "낙양", 58, 55, 56, 0, 156, 224, "안전", "-"); $gencount++;
41, "주태1",1414, 0, "낙양", 62, 55, 61, 0, 207, 261, "안전", "-"); $gencount++;
126, "주태2",1415, 0, "낙양", 74, 88, 60, 0, 171, 225, "정복", "필살"); $gencount++;
128, "주환",1416, 0, "낙양", 84, 86, 74, 0, 177, 238, "정복", "-"); $gencount++;
29, "진건",1417, 0, "낙양", 62, 70, 62, 0, 214, 292, "정복", "-"); $gencount++;
29, "진교",1418, 0, "낙양", 21, 25, 67, 0, 175, 237, "유지", "-"); $gencount++;
28, "진군",1419, 0, "낙양", 60, 38, 87, 0, 167, 235, "대의", "-"); $gencount++;
143, "진궁",1420, 0, "낙양", 77, 51, 90, 0, 154, 198, "할거", "신중"); $gencount++;
79, "진규",1421, 0, "낙양", 22, 19, 71, 0, 132, 206, "할거", "-"); $gencount++;
72, "진도",1422, 0, "낙양", 71, 85, 70, 0, 171, 237, "대의", "-"); $gencount++;
79, "진등",1423, 0, "낙양", 64, 62, 71, 0, 169, 207, "할거", "-"); $gencount++;
37, "진림",1424, 0, "낙양", 50, 28, 82, 0, 160, 217, "재간", "-"); $gencount++;
124, "진무",1425, 0, "낙양", 62, 74, 59, 0, 176, 215, "재간", "-"); $gencount++;
66, "진복",1426, 0, "낙양", 36, 27, 76, 0, 160, 226, "재간", "-"); $gencount++;
50, "진수",1427, 0, "낙양", 25, 29, 83, 0, 233, 297, "대의", "-"); $gencount++;
81, "진식",1428, 0, "낙양", 47, 68, 52, 0, 191, 230, "출세", "-"); $gencount++;
79, "진진",1429, 0, "낙양", 58, 38, 64, 0, 170, 235, "재간", "-"); $gencount++;
28, "진태",1430, 0, "낙양", 79, 76, 70, 0, 210, 260, "대의", "-"); $gencount++;
11, "진횡",1431, 0, "낙양", 38, 58, 47, 0, 161, 195, "출세", "-"); $gencount++;
21, "차주",1432, 0, "낙양", 55, 66, 62, 0, 164, 199, "안전", "-"); $gencount++;
11, "착융",1433, 0, "낙양", 62, 59, 21, 0, 161, 194, "출세", "-"); $gencount++;
36, "채모",1434, 0, "낙양", 79, 69, 68, 0, 155, 208, "정복", "궁병"); $gencount++;
36, "채중",1435, 0, "낙양", 58, 43, 55, 0, 168, 208, "출세", "-"); $gencount++;
36, "채화",1436, 0, "낙양", 56, 47, 49, 0, 166, 208, "안전", "-"); $gencount++;
66, "초주",1437, 0, "낙양", 22, 26, 81, 0, 201, 270, "대의", "-"); $gencount++;
20, "최염",1438, 0, "낙양", 43, 54, 67, 0, 162, 216, "대의", "-"); $gencount++;
60, "축융",1439, 0, "낙양", 59, 87, 25, 0, 193, 246, "정복", "척사"); $gencount++;
60, "타사대왕",1440, 0, "낙양", 61, 72, 67, 0, 186, 225, "출세", "척사"); $gencount++;
124, "태사자",1441, 0, "낙양", 71, 97, 65, 0, 166, 209, "대의", "무쌍"); $gencount++;
124, "태사향",1442, 0, "낙양", 51, 69, 50, 0, 189, 246, "재간", "-"); $gencount++;
12, "포륭",1443, 0, "낙양", 53, 74, 20, 0, 174, 208, "안전", "-"); $gencount++;
74, "풍습",1444, 0, "낙양", 36, 64, 44, 0, 182, 222, "재간", "-"); $gencount++;
7, "하의",1445, 0, "낙양", 49, 68, 25, 0, 161, 195, "출세", "-"); $gencount++;
121, "하제",1446, 0, "낙양", 74, 73, 64, 0, 171, 227, "재간", "-"); $gencount++;
90, "하진",1447, 0, "낙양", 49, 69, 37, 0, 135, 189, "왕좌", "-"); $gencount++;
24, "하후덕",1448, 0, "낙양", 67, 64, 39, 0, 178, 218, "출세", "-"); $gencount++;
26, "하후돈",1449, 0, "낙양", 88, 92, 71, 0, 156, 220, "의협", "돌격"); $gencount++;
19, "하후무",1450, 0, "낙양", 38, 33, 37, 0, 201, 259, "안전", "-"); $gencount++;
24, "하후상",1451, 0, "낙양", 67, 62, 71, 0, 181, 225, "출세", "-"); $gencount++;
26, "하후연",1452, 0, "낙양", 79, 90, 58, 0, 162, 219, "패권", "궁병"); $gencount++;
26, "하후위",1453, 0, "낙양", 73, 76, 71, 0, 204, 254, "정복", "-"); $gencount++;
26, "하후은",1454, 0, "낙양", 49, 51, 39, 0, 180, 208, "안전", "-"); $gencount++;
23, "하후패",1455, 0, "낙양", 78, 88, 69, 0, 202, 262, "대의", "-"); $gencount++;
20, "하후현",1456, 0, "낙양", 57, 23, 75, 0, 208, 254, "유지", "-"); $gencount++;
26, "하후혜",1457, 0, "낙양", 76, 66, 78, 0, 206, 242, "정복", "-"); $gencount++;
26, "하후화",1458, 0, "낙양", 77, 61, 80, 0, 207, 265, "정복", "-"); $gencount++;
22, "학소",1459, 0, "낙양", 89, 81, 86, 0, 185, 229, "대의", "견고"); $gencount++;
126, "한당",1460, 0, "낙양", 68, 67, 64, 0, 156, 225, "할거", "-"); $gencount++;
93, "한복",1461, 0, "낙양", 66, 59, 42, 0, 149, 191, "안전", "-"); $gencount++;
8, "한섬",1462, 0, "낙양", 39, 62, 35, 0, 159, 196, "출세", "-"); $gencount++;
48, "한수",1463, 0, "낙양", 66, 76, 77, 0, 142, 215, "대의", "기병"); $gencount++;
40, "한숭",1464, 0, "낙양", 21, 25, 70, 0, 154, 210, "재간", "-"); $gencount++;
7, "한충",1465, 0, "낙양", 41, 66, 29, 0, 151, 185, "안전", "-"); $gencount++;
9, "한현",1466, 0, "낙양", 43, 61, 20, 0, 163, 208, "유지", "-"); $gencount++;
27, "한호",1467, 0, "낙양", 60, 73, 45, 0, 164, 218, "유지", "-"); $gencount++;
79, "향랑",1468, 0, "낙양", 51, 21, 77, 0, 167, 247, "대의", "-"); $gencount++;
79, "향총",1469, 0, "낙양", 76, 42, 73, 0, 195, 240, "왕좌", "-"); $gencount++;
139, "허공",1470, 0, "낙양", 65, 63, 59, 0, 155, 200, "유지", "-"); $gencount++;
21, "허유",1471, 0, "낙양", 47, 47, 57, 0, 155, 204, "재간", "-"); $gencount++;
23, "허의",1472, 0, "낙양", 31, 74, 47, 0, 213, 263, "출세", "-"); $gencount++;
26, "허저",1473, 0, "낙양", 57, 98, 27, 0, 169, 226, "정복", "무쌍"); $gencount++;
87, "허정",1474, 0, "낙양", 18, 29, 74, 0, 152, 222, "재간", "-"); $gencount++;
12, "형도영",1475, 0, "낙양", 49, 78, 23, 0, 174, 208, "출세", "-"); $gencount++;
148, "호거아",1476, 0, "낙양", 35, 76, 61, 0, 164, 206, "안전", "-"); $gencount++;
76, "호반",1477, 0, "낙양", 61, 58, 46, 0, 179, 233, "재간", "-"); $gencount++;
20, "호분",1478, 0, "낙양", 71, 60, 61, 0, 222, 288, "할거", "-"); $gencount++;
27, "호주천",1479, 0, "낙양", 77, 75, 65, 0, 169, 230, "정복", "-"); $gencount++;
20, "호준",1480, 0, "낙양", 67, 60, 46, 0, 200, 256, "재간", "-"); $gencount++;
2, "화웅",1481, 0, "낙양", 68, 88, 24, 0, 155, 191, "출세", "돌격"); $gencount++;
131, "화핵",1482, 0, "낙양", 37, 27, 75, 0, 217, 278, "안전", "-"); $gencount++;
10, "화흠",1483, 0, "낙양", 18, 43, 75, 0, 157, 231, "출세", "-"); $gencount++;
21, "환범",1484, 0, "낙양", 20, 25, 81, 0, 199, 249, "유지", "-"); $gencount++;
127, "황개",1485, 0, "낙양", 78, 85, 69, 0, 154, 218, "왕좌", "징병"); $gencount++;
56, "황권",1486, 0, "낙양", 76, 46, 77, 0, 167, 240, "대의", "-"); $gencount++;
41, "황란",1487, 0, "낙양", 29, 70, 25, 0, 200, 264, "재간", "-"); $gencount++;
88, "황보숭",1488, 0, "낙양", 83, 63, 73, 0, 132, 195, "왕좌", "-"); $gencount++;
72, "황충",1489, 0, "낙양", 84, 94, 67, 0, 148, 222, "왕좌", "궁병"); $gencount++;
50, "황호",1490, 0, "낙양", 15, 17, 48, 0, 226, 263, "안전", "-"); $gencount++;
147, "후성",1491, 0, "낙양", 56, 62, 33, 0, 158, 199, "정복", "-"); $gencount++;
123, "가화",1492, 0, "낙양", 50, 66, 40, 0, 176, 224, "-", "-"); $gencount++;
999, "건석",1493, 0, "낙양", 21, 12, 61, 0, 155, 189, "-", "-"); $gencount++;
999, "견씨",1494, 0, "낙양", 35, 24, 58, 0, 182, 221, "-", "-"); $gencount++;
40, "견홍",1495, 0, "낙양", 76, 72, 66, 0, 224, 272, "-", "-"); $gencount++;
120, "고담",1496, 0, "낙양", 33, 21, 69, 0, 203, 244, "-", "-"); $gencount++;
101, "고유",1497, 0, "낙양", 56, 44, 73, 0, 174, 263, "-", "-"); $gencount++;
132, "곽마",1498, 0, "낙양", 68, 71, 49, 0, 239, 280, "-", "-"); $gencount++;
39, "관구수",1499, 0, "낙양", 58, 63, 35, 0, 206, 265, "-", "-"); $gencount++;
39, "관구전",1500, 0, "낙양", 63, 58, 68, 0, 224, 255, "-", "-"); $gencount++;
999, "관로",1501, 0, "낙양", 62, 21, 75, 0, 191, 256, "-", "-"); $gencount++;
65, "관정",1502, 0, "낙양", 35, 50, 73, 0, 158, 199, "-", "-"); $gencount++;
137, "교수",1503, 0, "낙양", 67, 69, 39, 0, 143, 195, "-", "-"); $gencount++;
33, "구건",1504, 0, "낙양", 43, 56, 69, 0, 239, 272, "-", "-"); $gencount++;
41, "구본",1505, 0, "낙양", 52, 41, 70, 0, 232, 269, "-", "-"); $gencount++;
12, "구성",1506, 0, "낙양", 56, 71, 31, 0, 157, 187, "-", "-"); $gencount++;
21, "국연",1507, 0, "낙양", 52, 21, 71, 0, 160, 219, "-", "-"); $gencount++;
99, "국의",1508, 0, "낙양", 83, 79, 50, 0, 146, 191, "-", "-"); $gencount++;
34, "금의",1509, 0, "낙양", 18, 40, 63, 0, 177, 218, "-", "-"); $gencount++;
76, "나헌",1510, 0, "낙양", 86, 67, 75, 0, 218, 270, "-", "-"); $gencount++;
999, "남두",1511, 0, "낙양", 35, 25, 54, 0, 130, 200, "-", "-"); $gencount++;
54, "냉포",1512, 0, "낙양", 70, 82, 69, 0, 176, 214, "-", "-"); $gencount++;
124, "노숙2",1513, 0, "낙양", 70, 55, 76, 0, 208, 274, "-", "-"); $gencount++;
42, "누규",1514, 0, "낙양", 54, 19, 88, 0, 143, 212, "-", "-"); $gencount++;
6, "누반",1515, 0, "낙양", 65, 76, 39, 0, 178, 207, "-", "-"); $gencount++;
130, "누현",1516, 0, "낙양", 23, 20, 68, 0, 223, 275, "-", "-"); $gencount++;
40, "당균",1517, 0, "낙양", 33, 19, 81, 0, 229, 264, "-", "-"); $gencount++;
32, "당빈",1518, 0, "낙양", 70, 74, 62, 0, 235, 294, "-", "-"); $gencount++;
999, "대교",1519, 0, "낙양", 42, 10, 54, 0, 177, 235, "-", "-"); $gencount++;
28, "대릉",1520, 0, "낙양", 64, 75, 45, 0, 199, 258, "-", "-"); $gencount++;
129, "동조",1521, 0, "낙양", 16, 15, 51, 0, 221, 281, "-", "-"); $gencount++;
114, "등수",1522, 0, "낙양", 35, 20, 44, 0, 228, 288, "-", "-"); $gencount++;
50, "마막",1523, 0, "낙양", 22, 17, 5, 0, 221, 265, "-", "-"); $gencount++;
116, "만욱",1524, 0, "낙양", 20, 18, 66, 0, 240, 272, "-", "-"); $gencount++;
120, "맹종",1525, 0, "낙양", 48, 48, 67, 0, 216, 271, "-", "-"); $gencount++;
38, "문호",1526, 0, "낙양", 65, 74, 45, 0, 227, 279, "-", "-"); $gencount++;
999, "미씨",1527, 0, "낙양", 59, 15, 68, 0, 176, 208, "-", "-"); $gencount++;
39, "반림",1528, 0, "낙양", 66, 79, 8, 0, 168, 225, "-", "-"); $gencount++;
129, "반장",1529, 0, "낙양", 77, 78, 69, 0, 177, 222, "-", "-"); $gencount++;
94, "방열",1530, 0, "낙양", 58, 82, 28, 0, 153, 190, "-", "-"); $gencount++;
55, "방희",1531, 0, "낙양", 59, 38, 69, 0, 153, 218, "-", "-"); $gencount++;
30, "배수",1532, 0, "낙양", 10, 11, 77, 0, 223, 271, "-", "-"); $gencount++;
8, "번능",1533, 0, "낙양", 70, 61, 47, 0, 158, 194, "-", "-"); $gencount++;
999, "번씨",1534, 0, "낙양", 32, 17, 45, 0, 176, 220, "-", "-"); $gencount++;
49, "보도근",1535, 0, "낙양", 64, 73, 50, 0, 170, 233, "-", "-"); $gencount++;
129, "보천",1536, 0, "낙양", 68, 60, 72, 0, 222, 272, "-", "-"); $gencount++;
121, "보협",1537, 0, "낙양", 73, 53, 75, 0, 216, 264, "-", "-"); $gencount++;
28, "부하",1538, 0, "낙양", 44, 36, 85, 0, 209, 255, "-", "-"); $gencount++;
26, "비요",1539, 0, "낙양", 70, 65, 73, 0, 192, 228, "-", "-"); $gencount++;
31, "사마주",1540, 0, "낙양", 63, 53, 62, 0, 227, 283, "-", "-"); $gencount++;
41, "사찬",1541, 0, "낙양", 61, 71, 54, 0, 215, 264, "-", "-"); $gencount++;
128, "설후",1542, 0, "낙양", 16, 14, 71, 0, 221, 271, "-", "-"); $gencount++;
36, "성공영",1543, 0, "낙양", 73, 58, 80, 0, 172, 220, "-", "-"); $gencount++;
126, "성만",1544, 0, "낙양", 61, 69, 66, 0, 225, 276, "-", "-"); $gencount++;
999, "소교",1545, 0, "낙양", 57, 23, 66, 0, 178, 218, "-", "-"); $gencount++;
46, "소유",1546, 0, "낙양", 51, 61, 48, 0, 164, 210, "-", "-"); $gencount++;
31, "소제2",1547, 0, "낙양", 22, 16, 78, 0, 224, 268, "-", "-"); $gencount++;
126, "손교",1548, 0, "낙양", 77, 60, 69, 0, 181, 219, "-", "-"); $gencount++;
116, "손기",1549, 0, "낙양", 62, 65, 52, 0, 227, 276, "-", "-"); $gencount++;
999, "손상향",1550, 0, "낙양", 72, 62, 42, 0, 193, 244, "-", "-"); $gencount++;
125, "손익",1551, 0, "낙양", 69, 75, 26, 0, 184, 204, "-", "-"); $gencount++;
125, "손진",1552, 0, "낙양", 64, 71, 48, 0, 234, 280, "-", "-"); $gencount++;
123, "송겸",1553, 0, "낙양", 61, 48, 44, 0, 175, 215, "-", "-"); $gencount++;
85, "순심",1554, 0, "낙양", 20, 21, 79, 0, 164, 208, "-", "-"); $gencount++;
31, "순욱2",1555, 0, "낙양", 10, 16, 77, 0, 225, 289, "-", "-"); $gencount++;
31, "순의",1556, 0, "낙양", 16, 11, 73, 0, 207, 281, "-", "-"); $gencount++;
129, "시삭",1557, 0, "낙양", 36, 66, 44, 0, 226, 268, "-", "-"); $gencount++;
29, "신창",1558, 0, "낙양", 51, 29, 46, 0, 210, 272, "-", "-"); $gencount++;
999, "악신",1559, 0, "낙양", 53, 12, 46, 0, 175, 228, "-", "-"); $gencount++;
138, "악취",1560, 0, "낙양", 56, 68, 58, 0, 157, 195, "-", "-"); $gencount++;
138, "양강",1561, 0, "낙양", 62, 70, 42, 0, 160, 199, "-", "-"); $gencount++;
21, "양부",1562, 0, "낙양", 68, 55, 85, 0, 178, 239, "-", "-"); $gencount++;
72, "양서",1563, 0, "낙양", 56, 62, 66, 0, 198, 260, "-", "-"); $gencount++;
34, "양습",1564, 0, "낙양", 67, 49, 73, 0, 168, 230, "-", "-"); $gencount++;
16, "양앙",1565, 0, "낙양", 65, 70, 39, 0, 172, 215, "-", "-"); $gencount++;
17, "양임",1566, 0, "낙양", 71, 78, 56, 0, 170, 215, "-", "-"); $gencount++;
32, "양제",1567, 0, "낙양", 69, 63, 71, 0, 226, 291, "-", "-"); $gencount++;
33, "양조2",1568, 0, "낙양", 65, 61, 67, 0, 223, 286, "-", "-"); $gencount++;
48, "양추2",1569, 0, "낙양", 66, 67, 61, 0, 172, 238, "-", "-"); $gencount++;
140, "양홍",1570, 0, "낙양", 19, 17, 76, 0, 152, 199, "-", "-"); $gencount++;
31, "양혼",1571, 0, "낙양", 60, 67, 63, 0, 220, 278, "-", "-"); $gencount++;
123, "여거",1572, 0, "낙양", 71, 58, 69, 0, 196, 256, "-", "-"); $gencount++;
130, "여대",1573, 0, "낙양", 83, 72, 70, 0, 161, 256, "-", "-"); $gencount++;
136, "염상",1574, 0, "낙양", 29, 27, 69, 0, 158, 199, "-", "-"); $gencount++;
36, "염행",1575, 0, "낙양", 70, 86, 38, 0, 159, 222, "-", "-"); $gencount++;
73, "영수",1576, 0, "낙양", 69, 70, 74, 0, 234, 264, "-", "-"); $gencount++;
39, "오거",1577, 0, "낙양", 49, 63, 32, 0, 151, 211, "-", "-"); $gencount++;
126, "오경",1578, 0, "낙양", 73, 60, 57, 0, 159, 203, "-", "-"); $gencount++;
999, "오국태",1579, 0, "낙양", 31, 11, 60, 0, 161, 222, "-", "-"); $gencount++;
126, "오찬",1580, 0, "낙양", 69, 41, 78, 0, 181, 245, "-", "-"); $gencount++;
23, "온회",1581, 0, "낙양", 42, 40, 78, 0, 178, 222, "-", "-"); $gencount++;
21, "왕기2",1582, 0, "낙양", 70, 66, 63, 0, 217, 281, "-", "-"); $gencount++;
32, "왕도",1583, 0, "낙양", 48, 44, 70, 0, 210, 269, "-", "-"); $gencount++;
123, "왕돈",1584, 0, "낙양", 60, 65, 41, 0, 198, 256, "-", "-"); $gencount++;
34, "왕릉",1585, 0, "낙양", 73, 60, 71, 0, 172, 251, "-", "-"); $gencount++;
63, "왕문",1586, 0, "낙양", 64, 67, 32, 0, 162, 205, "-", "-"); $gencount++;
32, "왕상",1587, 0, "낙양", 25, 19, 65, 0, 180, 268, "-", "-"); $gencount++;
34, "왕숙",1588, 0, "낙양", 35, 21, 80, 0, 195, 256, "-", "-"); $gencount++;
33, "왕업",1589, 0, "낙양", 32, 6, 46, 0, 220, 280, "-", "-"); $gencount++;
35, "왕충",1590, 0, "낙양", 42, 58, 21, 0, 152, 214, "-", "-"); $gencount++;
1, "우보",1591, 0, "낙양", 43, 63, 12, 0, 159, 192, "-", "-"); $gencount++;
122, "우사",1592, 0, "낙양", 70, 33, 79, 0, 217, 273, "-", "-"); $gencount++;
138, "원요",1593, 0, "낙양", 44, 42, 45, 0, 177, 206, "-", "-"); $gencount++;
95, "원유",1594, 0, "낙양", 57, 38, 73, 0, 150, 193, "-", "-"); $gencount++;
31, "위관",1595, 0, "낙양", 69, 45, 81, 0, 220, 291, "-", "-"); $gencount++;
129, "위막",1596, 0, "낙양", 58, 62, 60, 0, 221, 268, "-", "-"); $gencount++;
55, "유괴",1597, 0, "낙양", 75, 72, 66, 0, 165, 214, "-", "-"); $gencount++;
129, "유략",1598, 0, "낙양", 72, 68, 59, 0, 206, 260, "-", "-"); $gencount++;
45, "유반",1599, 0, "낙양", 74, 79, 48, 0, 168, 210, "-", "-"); $gencount++;
29, "유복",1600, 0, "낙양", 54, 50, 73, 0, 164, 208, "-", "-"); $gencount++;
78, "유선2",1601, 0, "낙양", 9, 21, 39, 0, 224, 264, "-", "-"); $gencount++;
139, "유섭",1602, 0, "낙양", 62, 79, 26, 0, 158, 190, "-", "-"); $gencount++;
28, "유소",1603, 0, "낙양", 66, 51, 73, 0, 195, 264, "-", "-"); $gencount++;
128, "유승",1604, 0, "낙양", 46, 69, 29, 0, 215, 258, "-", "-"); $gencount++;
129, "유찬",1605, 0, "낙양", 74, 75, 66, 0, 172, 255, "-", "-"); $gencount++;
129, "유평",1606, 0, "낙양", 65, 70, 67, 0, 218, 272, "-", "-"); $gencount++;
138, "유훈",1607, 0, "낙양", 51, 64, 50, 0, 163, 216, "-", "-"); $gencount++;
48, "이감",1608, 0, "낙양", 59, 67, 33, 0, 176, 211, "-", "-"); $gencount++;
19, "이승",1609, 0, "낙양", 13, 26, 32, 0, 201, 249, "-", "-"); $gencount++;
22, "이통",1610, 0, "낙양", 75, 84, 52, 0, 168, 211, "-", "-"); $gencount++;
138, "이풍2",1611, 0, "낙양", 72, 77, 50, 0, 158, 199, "-", "-"); $gencount++;
20, "이풍3",1612, 0, "낙양", 23, 25, 71, 0, 204, 254, "-", "-"); $gencount++;
29, "장구",1613, 0, "낙양", 69, 71, 47, 0, 201, 263, "-", "-"); $gencount++;
21, "장기",1614, 0, "낙양", 77, 35, 79, 0, 170, 223, "-", "-"); $gencount++;
74, "장남",1615, 0, "낙양", 71, 64, 38, 0, 187, 222, "-", "-"); $gencount++;
100, "장막",1616, 0, "낙양", 53, 52, 70, 0, 155, 195, "-", "-"); $gencount++;
7, "장만성",1617, 0, "낙양", 73, 83, 47, 0, 143, 184, "-", "-"); $gencount++;
135, "장반",1618, 0, "낙양", 56, 73, 66, 0, 227, 282, "-", "-"); $gencount++;
78, "장빈",1619, 0, "낙양", 30, 28, 67, 0, 216, 263, "-", "-"); $gencount++;
124, "장승",1620, 0, "낙양", 75, 68, 75, 0, 178, 244, "-", "-"); $gencount++;
999, "장양2",1621, 0, "낙양", 58, 50, 47, 0, 130, 184, "-", "-"); $gencount++;
68, "장억",1622, 0, "낙양", 82, 80, 54, 0, 190, 254, "-", "-"); $gencount++;
75, "장준",1623, 0, "낙양", 65, 67, 66, 0, 224, 263, "-", "-"); $gencount++;
20, "장집",1624, 0, "낙양", 31, 27, 74, 0, 196, 254, "-", "-"); $gencount++;
39, "장특",1625, 0, "낙양", 71, 53, 74, 0, 209, 265, "-", "-"); $gencount++;
96, "저곡",1626, 0, "낙양", 57, 53, 67, 0, 184, 204, "-", "-"); $gencount++;
128, "전기",1627, 0, "낙양", 51, 69, 55, 0, 231, 258, "-", "-"); $gencount++;
23, "전만",1628, 0, "낙양", 52, 74, 38, 0, 181, 235, "-", "-"); $gencount++;
128, "전상",1629, 0, "낙양", 5, 6, 11, 0, 208, 258, "-", "-"); $gencount++;
130, "전역",1630, 0, "낙양", 60, 62, 37, 0, 212, 265, "-", "-"); $gencount++;
75, "전예",1631, 0, "낙양", 80, 62, 83, 0, 171, 252, "-", "-"); $gencount++;
64, "전해",1632, 0, "낙양", 71, 63, 57, 0, 154, 199, "-", "-"); $gencount++;
123, "정봉2",1633, 0, "낙양", 67, 68, 52, 0, 198, 266, "-", "-"); $gencount++;
22, "정의",1634, 0, "낙양", 17, 3, 66, 0, 184, 220, "-", "-"); $gencount++;
81, "제갈교",1635, 0, "낙양", 55, 17, 77, 0, 204, 228, "-", "-"); $gencount++;
40, "제갈서",1636, 0, "낙양", 45, 43, 27, 0, 218, 286, "-", "-"); $gencount++;
25, "조충",1637, 0, "낙양", 14, 7, 80, 0, 196, 208, "-", "-"); $gencount++;
121, "종리목",1638, 0, "낙양", 84, 68, 75, 0, 214, 269, "-", "-"); $gencount++;
22, "종육",1639, 0, "낙양", 27, 11, 71, 0, 223, 263, "-", "-"); $gencount++;
122, "좌혁",1640, 0, "낙양", 60, 66, 51, 0, 232, 280, "-", "-"); $gencount++;
36, "주령",1641, 0, "낙양", 77, 70, 69, 0, 170, 236, "-", "-"); $gencount++;
115, "주앙",1642, 0, "낙양", 75, 64, 64, 0, 162, 195, "-", "-"); $gencount++;
52, "주포",1643, 0, "낙양", 59, 72, 12, 0, 191, 225, "-", "-"); $gencount++;
11, "주흔",1644, 0, "낙양", 67, 53, 77, 0, 159, 196, "-", "-"); $gencount++;
140, "진기",1645, 0, "낙양", 58, 67, 46, 0, 165, 198, "-", "-"); $gencount++;
142, "진란",1646, 0, "낙양", 65, 70, 43, 0, 157, 204, "-", "-"); $gencount++;
25, "진랑",1647, 0, "낙양", 57, 70, 38, 0, 192, 234, "-", "-"); $gencount++;
12, "진응",1648, 0, "낙양", 62, 69, 49, 0, 172, 208, "-", "-"); $gencount++;
124, "진표",1649, 0, "낙양", 62, 49, 74, 0, 204, 237, "-", "-"); $gencount++;
999, "채염",1650, 0, "낙양", 40, 22, 64, 0, 168, 237, "-", "-"); $gencount++;
999, "초선",1651, 0, "낙양", 66, 15, 72, 0, 176, 211, "-", "-"); $gencount++;
135, "초이",1652, 0, "낙양", 54, 65, 55, 0, 219, 266, "-", "-"); $gencount++;
65, "추단",1653, 0, "낙양", 63, 71, 36, 0, 148, 193, "-", "-"); $gencount++;
999, "추씨",1654, 0, "낙양", 36, 13, 54, 0, 165, 225, "-", "-"); $gencount++;
71, "추정",1655, 0, "낙양", 67, 65, 66, 0, 144, 193, "-", "-"); $gencount++;
145, "파재",1656, 0, "낙양", 69, 75, 52, 0, 145, 184, "-", "-"); $gencount++;
22, "포신",1657, 0, "낙양", 78, 60, 83, 0, 152, 192, "-", "-"); $gencount++;
114, "하식",1658, 0, "낙양", 18, 38, 29, 0, 230, 284, "-", "-"); $gencount++;
36, "하안",1659, 0, "낙양", 6, 27, 72, 0, 190, 249, "-", "-"); $gencount++;
999, "하후씨",1660, 0, "낙양", 29, 16, 47, 0, 186, 249, "-", "-"); $gencount++;
5, "학맹",1661, 0, "낙양", 57, 66, 41, 0, 156, 197, "-", "-"); $gencount++;
98, "한거자",1662, 0, "낙양", 53, 59, 30, 0, 158, 200, "-", "-"); $gencount++;
19, "한덕",1663, 0, "낙양", 62, 79, 24, 0, 171, 228, "-", "-"); $gencount++;
140, "한윤",1664, 0, "낙양", 27, 24, 68, 0, 155, 197, "-", "-"); $gencount++;
999, "허소",1665, 0, "낙양", 53, 27, 60, 0, 150, 195, "-", "-"); $gencount++;
30, "호열",1666, 0, "낙양", 77, 69, 76, 0, 225, 272, "-", "-"); $gencount++;
76, "호제",1667, 0, "낙양", 58, 42, 68, 0, 207, 264, "-", "-"); $gencount++;
149, "호진",1668, 0, "낙양", 65, 77, 13, 0, 146, 190, "-", "-"); $gencount++;
29, "호질",1669, 0, "낙양", 73, 50, 75, 0, 192, 250, "-", "-"); $gencount++;
7, "환계",1670, 0, "낙양", 12, 25, 67, 0, 156, 221, "-", "-"); $gencount++;
56, "황숭",1671, 0, "낙양", 68, 64, 74, 0, 208, 263, "-", "-"); $gencount++;
999, "황승언",1672, 0, "낙양", 68, 17, 81, 0, 165, 222, "-", "-"); $gencount++;
999, "황월영",1673, 0, "낙양", 58, 14, 75, 0, 186, 235, "-", "-"); $gencount++;
45, "황조",1674, 0, "낙양", 74, 65, 57, 0, 148, 208, "-", "-"); $gencount++;
48, "후선",1675, 0, "낙양", 56, 66, 35, 0, 175, 228, "-", "-"); $gencount++;
8, "휴고",1676, 0, "낙양", 61, 72, 40, 0, 151, 199, "-", "-"); $gencount++;
98, "휴원진",1677, 0, "낙양", 53, 63, 38, 0, 155, 200, "-", "-"); $gencount++;
22, "희지재",1678, 0, "낙양", 24, 5, 86, 0, 157, 194, "-", "-"); $gencount++;
+39 -20
View File
@@ -47,7 +47,7 @@ if ($me['newmsg'] == 1 || $me['newvote'] == 1) {
], 'owner=%i', $userID);
}
$plock = $db->queryFirstField('SELECT plock FROM plock LIMIT 1');
$plock = boolval($db->queryFirstField('SELECT plock FROM plock WHERE `type`="GAME" LIMIT 1'));
$con = checkLimit($me['con']);
if ($con >= 2) {
@@ -83,11 +83,13 @@ if ($gameStor->npcmode == 0) {
$npcmode = "선택 생성";
}
$color = "cyan";
$mapTheme = $gameStor->map_theme;
$serverName = UniqueConst::$serverName;
$serverCnt = $gameStor->server_cnt;
$auctionCount = $db->queryFirstField('SELECT count(`no`) FROM auction');
$isTournamentActive = $gameStor->tournament > 0;
$isTournamentApplicationOpen = $gameStor->tournament == 1;
$isBettingActive = $gameStor->tournament == 6;
$myNationStatic = getNationStaticInfo($generalObj->getNationID());
$nationColorType = substr($myNationStatic['color'] ?? '#000000', 1);
@@ -123,13 +125,34 @@ if (!$otherTextInfo) {
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/map.css') ?>
<?= WebUtil::printStaticValues([
//deprecated, staticValues를 이용할 것
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'commandList' => getCommandTable($generalObj),
'serverNow' => TimeUtil::now(false),
'baseColor2' => GameConst::$basecolor2,
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'staticValues' => [
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'commandList' => getCommandTable($generalObj),
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'mapName' => GameConst::$mapName,
'unitSet' => GameConst::$unitSet,
]
]) ?>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
</head>
@@ -149,14 +172,14 @@ if (!$otherTextInfo) {
<?= $scenario ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC : <?= $extend ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC상성 : <?= $fiction ?>
NPC 수, 상성 : <?= $extend ?>,<?= $fiction ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC선택 : <?= $npcmode ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
토너먼트 : <?= getTournamentTermText() ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
기타 설정: <?= $otherTextInfo ?>
</div>
@@ -165,19 +188,15 @@ if (!$otherTextInfo) {
<div class="s-border-t col py-2 col-4 col-md-2">전체 접속자 수 : <?= $gameStor->online_user_cnt ?> 명</div>
<div class="s-border-t col py-2 col-4 col-md-2">턴당 갱신횟수 : <?= $gameStor->conlimit ?>회</div>
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(3) ?></div>
<div class="s-border-t py-2 col col-6 col-md-4"><?php if ($gameStor->tournament == 0) : ?>
<span style='color:magenta'>현재 토너먼트 경기 없음</span>
<div class="s-border-t py-2 col col-6 col-md-4">
<?php if ($isTournamentActive) : ?>
↑<span style='color:cyan'><?= (['전력전', '통솔전', '일기토', '설전',])[$gameStor->tnmt_type] ?? '' ?> <?= getTournament($gameStor->tournament) ?> <?= getTournamentTime() ?></span>↑
<?php else : ?>
<span style='color:cyan'><?=
([
'전력전', '통솔전', '일기토', '설전',
])[$gameStor->tnmt_type] ?? '' ?> <?= getTournament($gameStor->tournament) ?> <?= getTournamentTime() ?></span>↑
<span style='color:magenta'>현재 토너먼트 경기 없음</span>
<?php endif; ?>
</div>
<div class="s-border-t py-2 col col-6 col-md-2">
<div style="display:inline-block;"><?= !$plock ? ("<span style='color:cyan;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") : ("<span style='color:magenta;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") ?></div>
<div style="display:inline-block;"><?= $plock ? ("<span style='color:magenta;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") : ("<span style='color:cyan;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") ?></div>
</div>
<div class="s-border-t py-2 col col-6 col-md-2">
<?php if ($auctionCount > 0) : ?>
@@ -237,7 +256,7 @@ if (!$otherTextInfo) {
</div>
<?php endif; ?>
<div id="map_view" class="gx-0">
<div id="mapZone" class="view-item"><?= getMapHtml($mapTheme) ?></div>
<div id="mapZone" class="view-item"><?= getMapHtml() ?></div>
<div class="view-item" id="reservedCommandZone">
<div id="reservedCommandList"></div>
<div id="actionMiniPlate" class="gx-0 row">
@@ -253,7 +272,7 @@ if (!$otherTextInfo) {
<div id="nation-position"><?php myNationInfo($generalObj); ?></div>
<div id="general-position"><?php generalInfo($generalObj); ?></div>
<div id="generalCommandButton" class="row gx-0">
<div class="buttonPlate bg2"><?= commandButton(['btnClass' => 'btn btn-sammo-nation']) ?></div>
<div class="buttonPlate bg2"><?= commandButton(['btnClass' => 'btn btn-sammo-nation', 'isTournamentApplicationOpen' => $isTournamentApplicationOpen, 'isBettingActive' => $isBettingActive]) ?></div>
</div>
</div>
</div>
@@ -353,7 +372,7 @@ if (!$otherTextInfo) {
국가 메뉴
</div>
<ul class="dropdown-menu" aria-labelledby="navbarNation" id="navbarNationItems">
<?= commandButton(['btnBegin' => '<li>', 'btnEnd' => '</li>', 'btnClass' => 'dropdown-item']) ?>
<?= commandButton(['btnBegin' => '<li>', 'btnEnd' => '</li>', 'btnClass' => 'dropdown-item', 'isTournamentApplicationOpen' => $isTournamentApplicationOpen, 'isBettingActive' => $isBettingActive]) ?>
</ul>
</li>
<li class="nav-item dropup">
-76
View File
@@ -1,76 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$betTarget = Util::getPost('target', 'int', -1);
$betGold = Util::getPost('amount', 'int', 0);
if($betTarget < 0 || $betTarget >= 16 || $betGold < 10 || $betGold > 1000){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 입력입니다'
]);
}
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$generalID = $session->generalID;
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("베팅", 1);
$tournament = $gameStor->tournament;
if($tournament != 6) {
Json::die([
'result'=>false,
'reason'=>'베팅 기간이 아닙니다.'
]);
}
$myGold = $db->queryFirstField('SELECT gold FROM general WHERE no = %i', $generalID);
$bets = $db->queryFirstList('SELECT * FROM betting WHERE general_id = %i', $generalID);
$bets = array_splice($bets, -16);
$totalBet = array_sum($bets);
$oldBet = $bets[$betTarget];
$targetKey = "bet{$betTarget}";
if($myGold - $betGold < 500){
Json::die([
'result'=>false,
'reason'=>'여유 자금이 부족합니다.'
]);
}
if($betGold + $totalBet > 1000){
Json::die([
'result'=>false,
'reason'=>'베팅 허용 금액을 초과했습니다.'
]);
}
$db->update('betting', [
$targetKey=>$db->sqleval('%b + %i', $targetKey, $betGold),
], 'general_id = %i', $generalID);
$db->update('general', [
'gold'=>$db->sqleval('gold - %i', $betGold),
], 'no = %i', $generalID);
$db->update('rank_data', [
'value'=>$db->sqleval('value + %i', $betGold)
], 'general_id = %i AND type = "betgold"', $generalID);
$db->update('betting', [
$targetKey=>$db->sqleval('%b + %i', $targetKey, $betGold)
], 'general_id = 0');
Json::die([
'result'=>true,
'reason'=>'SUCCESS'
]);
-41
View File
@@ -1,41 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$turnAmount = Util::getPost('amount', 'int');
$db = DB::db();
$me = $db->queryFirstRow('SELECT no,nation,officer_level FROM general WHERE owner=%i', $userID);
if($me['nation'] == 0){
Json::die([
'result'=>false,
'reason'=>'국가에 소속되어 있지 않습니다.',
]);
}
if($me['officer_level'] < 5){
Json::die([
'result'=>false,
'reason'=>'수뇌가 아닙니다.',
]);
}
if($turnAmount > 0){
pushNationCommand($me['nation'], $me['officer_level']);
}
else{
pullNationCommand($me['nation'], $me['officer_level']);
}
Json::die([
'result'=>true,
'reason'=>'success',
]);
+1 -3
View File
@@ -41,8 +41,6 @@ if ($permission < 4) {
]);
}
$reason = trim($reason);
$letter = $db->queryFirstRow('SELECT * FROM ng_diplomacy WHERE no=%i AND src_nation_id = %i AND state = \'proposed\'', $letterNo, $me['nation']);
if(!$letter){
Json::die([
@@ -66,7 +64,7 @@ $unlimited = new \DateTime('9999-12-31');
$aux['reason'] = [
'who'=>$me['no'],
'action'=>'cancelled',
'reason'=>$reason
'reason'=>'회수',
];
$db->update('ng_diplomacy', [
'state'=>'cancelled',
-103
View File
@@ -1,103 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("사령부", 1);
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,penalty,permission FROM general WHERE owner=%i', $userID);
$nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation = %i', $me['nation']);
$nationID = $me['nation'];
$con = checkLimit($me['con']);
if($con >= 2) {
Json::die([
'result'=>false,
'reason'=>"접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 접속 가능 시각 : {$me['turntime']})"
]);
}
$permission = checkSecretPermission($me);
if($permission < 0){
Json::die([
'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.'
]);
echo '국가에 소속되어있지 않습니다.';
die();
}
else if ($permission < 1) {
Json::die([
'result'=>false,
'reason'=>'수뇌부가 아니거나 사관년도가 부족합니다.'
]);
die();
}
$date = TimeUtil::now();
// 명령 목록
[$year, $month, $turnterm] = $gameStor->getValuesAsArray(['year', 'month', 'turnterm']);
$lv = getNationChiefLevel($nationLevel);
$turn = [];
$generals = [];
foreach($db->query('SELECT no,name,turntime,npc,city,nation,officer_level FROM general WHERE nation = %i AND officer_level >= 5',$nationID) as $rawGeneral){
$generals[$rawGeneral['officer_level']] = new General($rawGeneral, null, null, null, $year, $month, false);
}
$nationTurnList = [];
foreach(
$db->queryAllLists(
'SELECT officer_level, turn_idx, action, arg, brief FROM nation_turn WHERE nation_id = %i ORDER BY officer_level DESC, turn_idx ASC',
$me['nation']
) as [$officer_level, $turn_idx, $action, $arg, $brief]
){
if(!key_exists($officer_level, $nationTurnList)){
$nationTurnList[$officer_level] = [];
}
$nationTurnList[$officer_level][$turn_idx] = $brief;
}
$nationTurnBrief = [];
foreach($nationTurnList as $officer_level=>$turnBrief){
if(!key_exists($officer_level, $generals)){
$nationTurnBrief[$officer_level] = [
'name'=>null,
'turnTime'=>null,
'officerLevelText'=>getOfficerLevelText($officer_level, $nationLevel),
'npcType'=>null,
'turn'=>$turnBrief
];
continue;
}
$general = $generals[$officer_level];
$nationTurnBrief[$officer_level] = [
'name'=>$general->getName(),
'turnTime'=>$general->getTurnTime($general::TURNTIME_FULL),
'officerLevel'=>$general->getVar('officer_level'),
'officerLevelText'=>getOfficerLevelText($general->getVar('officer_level'), $nationLevel),
'npcType'=>$general->getNPCType(),
'turn'=>$turnBrief,
];
}
$date = substr(TimeUtil::now(), 14);
Json::die([
'result'=>true,
'reason'=>'success',
'date'=>$date,
'nationTurnBrief'=>$nationTurnBrief,
'isChief'=>($me['officer_level'] > 4),
'officerLevel'=>$me['officer_level'],
'turnTerm'=>$turnterm
]);
-109
View File
@@ -1,109 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireLogin([]);
$userID = Session::getUserID();
$db = DB::db();
$withToken = Util::getPost('with_token', 'bool', false);
$gameStor = KVStorage::getStorage($db, 'game_env');
if($session->isGameLoggedIn()){
increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
]);
}
}
else{
$availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00';
$now = new \DateTimeImmutable();
if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){
Json::die([
'result'=>false,
'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall
]);
}
$availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s');
$session->availableNextCallGetGeneralList = $availableNextCall;
}
$session->setReadOnly();
$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general');
$ownerNameList = [];
if($gameStor->isunited){
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
$ownerNameList[$ownerID] = $ownerName;
}
}
$generalList = [];
foreach($rawGeneralList as $rawGeneral){
[$owner,$no,$picture,$imgsvr,$npc,$age,$nation,$special,$special2,$personal,$name,$ownerName,$injury,$leadership,$strength,$intel,$experience,$dedication,$officerLevel,$killturn,$connectCnt] = $rawGeneral;
if(key_exists($owner, $ownerNameList)){
$ownerName = $ownerNameList[$owner];
}
$nationArr = getNationStaticInfo($nation);
$lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']);
$generalList[] = [
$no,
$picture,
$imgsvr,
$npc,
$age,
$nationArr['name'],
getGeneralSpecialDomesticName($special),
getGeneralSpecialWarName($special2),
getGenChar($personal),
$name,
$npc==1?$ownerName:null,
$injury,
$leadership,
$lbonus,
$strength,
$intel,
getExpLevel($experience),
getHonor($experience),
getDed($dedication),
getOfficerLevelText($officerLevel, $nationArr['level']),
$killturn,
$connectCnt
];
}
$result = [
'result'=>'true',
'list'=>$generalList,
];
if($withToken){
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
$tokens = [];
foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){
$validUntil = $token['valid_until'];
foreach(Json::decode($token['pick_result']) as $pickResult){
$tokens[$pickResult['no']]=$pickResult['keepCnt'];
}
}
$result['token'] = $tokens;
}
Json::die($result);
-184
View File
@@ -1,184 +0,0 @@
<?php
namespace sammo;
//통합 세력장수&암행부 viewer
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin([])->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$reqType = Util::getReq('req', 'int', 1);
$reqForce = Util::getReq('force', 'bool', false);
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("세력장수", 1);
$me = $db->queryFirstRow('SELECT con, turntime, belong, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
Json::die([
'result' => false,
'reason' => '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
]);
}
$nationID = $me['nation'];
$permission = checkSecretPermission($me, true);
if ($reqForce && $reqType > $permission) {
Json::die([
'result' => false,
'reason' => '권한이 부족합니다.'
]);
}
$permission = min($reqType, $permission);
$nationArr = getNationStaticInfo($nationID);
$viewColumns = [
'no' => 0,
'name' => 0,
'owner_name' => 9,
'nation' => 0,
'city' => 1,
'officer_level' => 2,
'officer_city' => 2,
'npc' => 0,
'defence_train' => 2,
'troop' => 2,
'injury' => 0,
'leadership' => 0,
'strength' => 0,
'intel' => 0,
'experience' => 1,
'explevel' => 0,
'dedication' => 1,
'dedlevel' => 0,
'gold' => 0,
'rice' => 0,
'crewtype' => 2,
'crew' => 2,
'train' => 2,
'atmos' => 2,
'killturn' => 0,
'turntime' => 2,
'picture' => 0,
'imgsvr' => 0,
'age' => 0,
'special' => 0,
'special2' => 0,
'personal' => 0,
'belong' => 0,
'horse' => 2,
'weapon' => 2,
'book' => 2,
'item' => 2,
'connect' => 0
];
$customViewColumns = [
'officerLevel' => 0,
'officerLevelText' => 0,
'lbonus' => 0,
'ownerName' => 0,
'honorText' => 0
];
function getOfficerLevel($rawGeneral)
{
global $permission;
$level = $rawGeneral['officer_level'];
if ($level >= 5) {
return $level;
}
if ($permission > 1) {
return $level;
}
return 1;
}
$specialViewFilter = [
'officerLevel' => function ($rawGeneral){
return getOfficerLevel($rawGeneral);
},
'special' => function ($rawGeneral) {
return getGeneralSpecialDomesticName($rawGeneral['special']);
},
'special2' => function ($rawGeneral) {
return getGeneralSpecialWarName($rawGeneral['special2']);
},
'personal' => function ($rawGeneral) {
return getGenChar($rawGeneral['personal']);
},
'lbonus' => function ($rawGeneral) use ($nationArr) {
return calcLeadershipBonus($rawGeneral['officer_level'], $nationArr['level']);
},
'ownerName' => function ($rawGeneral) {
if ($rawGeneral['npc'] != 1) {
return null;
}
return $rawGeneral['owner_name'];
},
'officerLevelText' => function ($rawGeneral) use ($nationArr) {
$level = getOfficerLevel($rawGeneral);
return getOfficerLevelText($level, $nationArr['level']);
},
'honorText' => function ($rawGeneral) {
return getHonor($rawGeneral['experience']);
},
'dedLevelText' => function ($rawGeneral) {
return getDedLevelText($rawGeneral['dedLevel']);
},
'turntime' => function ($rawGeneral) {
//'0000-00-00 11:23';
return substr($rawGeneral['turntime'], 11, 5);
}
];
[$queryColumns, $rankColumns] = General::mergeQueryColumn(array_keys($viewColumns), 1);
$rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE nation = %i', Util::formatListOfBackticks($queryColumns), $nationID), 'no');
$resultColumns = [];
foreach ($viewColumns as $column => $reqPermission) {
if ($reqPermission > $permission) {
continue;
}
$resultColumns[] = $column;
}
foreach ($customViewColumns as $column => $reqPermission) {
if ($reqPermission > $permission) {
continue;
}
$resultColumns[] = $column;
}
$generalList = [];
foreach ($rawGeneralList as $rawGeneral) {
//General 생성?
$item = [];
foreach ($resultColumns as $column) {
if (key_exists($column, $specialViewFilter)) {
$value = $specialViewFilter[$column]($rawGeneral);
}
else{
$value = $rawGeneral[$column];
}
$item[] = $value;
}
$generalList[] = $item;
}
$result = [
'result' => true,
'column' => $resultColumns,
'list' => $generalList,
];
Json::die($result);
-46
View File
@@ -1,46 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$year = Util::getReq('year', 'int');
$month = Util::getReq('month', 'int');
$serverID = Util::getReq('serverID', 'string', null);
$url = '/a_history.php';
if(!strpos($_SERVER['HTTP_REFERER'], $url)) {
Json::die([
'result'=>false,
'reason'=>'Invalid Referer'
]);
}
if($year === null || !$month) {
Json::die([
'result'=>false,
'reason'=>'year, month가 지정되지 않았습니다'
]);
}
if(!$serverID){
$serverID = UniqueConst::$serverID;
}
//로그인 검사
$session = Session::requireGameLogin([])->setReadOnly();
$db = DB::db();
$map = $db->queryFirstField('SELECT map FROM ng_history WHERE server_id=%s AND year=%i AND month=%i', $serverID, $year, $month);
if(!$map){
Json::die([
'result'=>false,
'reason'=>'해당하는 연월의 지도가 없습니다'
]);
}
Json::die($map, Json::PASS_THROUGH);
+8 -15
View File
@@ -31,17 +31,12 @@ $now = time();
if($mapInfo && ($now - $mapInfo['timestamp'] < 600)){
$mapEtag = $mapInfo['etag'];
$mapModified = $mapInfo['timestamp'];
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $mapModified)." GMT");
header("Etag: $mapEtag");
if (
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']??'2000-01-01') === $mapModified ||
trim($_SERVER['HTTP_IF_NONE_MATCH']??'') === $mapEtag
) {
header("HTTP/1.1 304 Not Modified");
die();
}
WebUtil::setCacheHeader(new APICacheResult(TimeUtil::secondsToDateTime($mapModified), $mapEtag));
$reqMapEtag = WebUtil::parseETag();
$reqModifiedSince = WebUtil::parseLastModified();
if($mapEtag === $reqMapEtag || $mapModified === $reqModifiedSince){
WebUtil::dieWithNotModified();
}
Json::die($mapInfo['data'], 0);
}
@@ -65,10 +60,9 @@ $rawMap = getWorldMap([
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$mapTheme = $gameStor->map_theme ?? 'che';
$rawMap['history'] = $history;
$rawMap['theme'] = $mapTheme;
$rawMap['theme'] = GameConst::$mapName;
$etag = hash('sha256', $serverID.$now);
$map = [
@@ -77,7 +71,6 @@ $map = [
'data'=>$rawMap,
];
$cache->save("recent_map", $map);
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $now)." GMT");
header("Etag: $etag");
WebUtil::setCacheHeader(new APICacheResult(TimeUtil::secondsToDateTime($now), $etag));
Json::die($map['data'], 0);
+1 -1
View File
@@ -241,7 +241,7 @@ function do추방(General $general, int $myOfficerLevel):?string{
}
$general->setVar('troop', 0);
if($general->getNPCType() >= 2 && ($env['scenario'] < 100 || Util::randBool(0.01))) {
if($general->getNPCType() >= 2 && Util::randBool(GameConst::$npcBanMessageProb)) {
$str = Util::choiceRandom([
'날 버리다니... 곧 전장에서 복수해주겠다...',
+1
View File
@@ -6,6 +6,7 @@ include "func.php";
WebUtil::requireAJAX();
/** @var int|null */
$pick = Util::getPost('pick', 'int');
if(!$pick){
-66
View File
@@ -1,66 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$session = Session::requireGameLogin([])->setReadOnly();
increaseRefresh("사령턴 입력", 0);
$generalID = $session->generalID;
$action = Util::getPost('action', 'string');
$arg = Json::decode(Util::getPost('arg', 'string'));
$turnList = Util::getPost('turnList', 'array_int');
if(!is_array($turnList) || !$turnList){
Json::die([
'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.',
'test'=>'post',
]);
}
if(!$action){
Json::die([
'result'=>false,
'reason'=>'action이 입력되지 않았습니다.',
'test'=>'post'
]);
}
if(!in_array($action, Util::array_flatten(GameConst::$availableChiefCommand))){
Json::die([
'result'=>false,
'reason'=>'사용할 수 없는 커맨드입니다.',
'test'=>'post'
]);
}
if($arg === null){
$arg = [];
}
if(!is_array($arg)){
Json::die([
'result'=>false,
'reason'=>'올바른 arg 형태가 아닙니다.',
'test'=>'post'
]);
}
$result = setNationCommand($generalID, $turnList, $action, $arg);
if(!key_exists('result', $result)){
$result['result'] = false;
}
if(!key_exists('arg_test', $result)){
$result['arg_test'] = false;
}
if(!key_exists('reason', $result)){
throw new MustNotBeReachedException('reason이 왜 없어?');
}
Json::die($result);
-55
View File
@@ -1,55 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$session = Session::requireGameLogin([])->setReadOnly();
increaseRefresh("턴 입력", 0);
$generalID = $session->generalID;
$action = Util::getPost('action', 'string');
$arg = Json::decode(Util::getPost('arg', 'string'));
$turnList = Util::getPost('turnList', 'array_int');
if(!is_array($turnList) || !$turnList){
Json::die([
'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.',
'test'=>'post',
]);
}
if(!$action){
Json::die([
'result'=>false,
'reason'=>'action이 입력되지 않았습니다.',
'test'=>'post'
]);
}
if(!in_array($action, Util::array_flatten(GameConst::$availableGeneralCommand))){
Json::die([
'result'=>false,
'reason'=>'사용할 수 없는 커맨드입니다.',
'test'=>'post'
]);
}
if($arg === null){
$arg = [];
}
if(!is_array($arg)){
Json::die([
'result'=>false,
'reason'=>'올바른 arg 형태가 아닙니다.',
'test'=>'post'
]);
}
Json::die(setGeneralCommand($generalID, $turnList, $action, $arg));
+25 -20
View File
@@ -1,6 +1,9 @@
<?php
namespace sammo;
use Ds\Map;
use sammo\Enums\RankColumn;
include "lib.php";
include "func.php";
@@ -54,7 +57,7 @@ $defaultCheck = [
['year', 0]
],
'array'=>[
'attackerGeneral', 'attackerCity', 'attackerNation',
'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation'
],
];
@@ -84,14 +87,14 @@ $rawDefenderNation = $query['defenderNation'];
$generalCheck = [
'required'=>[
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item',
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item',
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'recent_war', 'warnum', 'killnum', 'killcrew',
],
'integer'=>[
'no', 'nation', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp',
'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp',
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'warnum', 'killnum', 'killcrew',
],
@@ -154,18 +157,18 @@ foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
]);
}
$rawDefenderGeneral['owner'] = 0;
$defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
}
$cityCheck = [
'required'=>[
'city', 'nation', 'supply', 'name',
'pop', 'agri', 'comm', 'secu', 'def', 'wall',
'city', 'nation', 'supply', 'name',
'pop', 'agri', 'comm', 'secu', 'def', 'wall',
'trust', 'level',
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'dead', 'state', 'conflict',
'dead', 'state', 'conflict',
],
'numeric'=>[
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
@@ -258,7 +261,7 @@ if($action == 'reorder'){
foreach($defenderList as $defenderGeneral){
$order[] = $defenderGeneral->getID();
}
Json::die([
'result'=>true,
'reason'=>'success',
@@ -280,19 +283,21 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
$startYear = $gameStor->startyear;
$cityRate = Util::round(($year - $startYear) / 1.5) + 60;
function extractRankVar(array $rawVal):array{
$rankVars = [];
function extractRankVar(array $rawVal):Map{
$rankVars = new Map;
foreach($rawVal as $rawKey=>$rawVal){
if(key_exists($rawKey, General::RANK_COLUMN)){
$rankVars[$rawKey] = $rawVal;
$key = RankColumn::tryFrom($rawKey);
if($key === null){
continue;
}
$rankVars[$key] = $rawVal;
}
return $rankVars;
}
function simulateBattle(
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$startYear, $year, $month, $cityRate
){
$attacker = new WarUnitGeneral(
@@ -310,7 +315,7 @@ function simulateBattle(
$attackerRice = $rawAttacker['rice'];
$defenderRice = 0;
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
if($prevDefender !== null){
$prevDefender->getLogger()->rollback();
@@ -393,13 +398,13 @@ $defendersActivatedSkills = [];
foreach(Util::range($repeatCnt) as $repeatIdx){
/** @var WarUnit $attacker */
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$startYear, $year, $month, $cityRate
);
$lastWarLog = Util::mapWithKey(function($key, $values){
return ConvertLog(join('<br>', $values));
}, $attacker->getLogger()->rollback());
}, $attacker->getLogger()->rollback());
$avgPhase += $attacker->getPhase() / $repeatCnt;
@@ -443,7 +448,7 @@ foreach(Util::range($repeatCnt) as $repeatIdx){
$activatedSkills[$skillName] += $skillCnt / $repeatCnt;
}
}
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ $loader->addClassMap((function () {
//디버그용 매크로
ini_set("session.cache_expire", 10080); // minutes
ini_set("session.cache_expire", "10080"); // minutes
ob_start();
-1
View File
@@ -1 +0,0 @@
0
-53
View File
@@ -1,53 +0,0 @@
로그활성화
show variables like '%log%';
ALTER TABLE mysql.general_log
ADD COLUMN seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT AFTER argument,
ADD PRIMARY KEY(seq),
ENGINE=MYISAM;
set global expire_logs_days=7;
set global log_output='TABLE';
set global general_log=1;
select count(*) from mysql.general_log;
select * from mysql.general_log limit 100;
set global general_log=0;
truncate mysql.general_log;
캐시들
show variables like '%cache%';
show status like '%cache%';
show variables like '%key%';
show status like '%key%';
key_buffer_size 줄이자. 현16M -> 8M이하
myisam_sort_buffer_size 줄이자. 현8M -> 2M
innodb 설정
기존 Antelope 포맷은 가변컬럼의 767바이트까지만 저장하고 나머지는 offset하여 외부에 저장한다.
그런데 innodb는 1개 행이 최대 8KB만 저장 가능하므로 가변컬럼이 11개 이상인 경우는 오류 위험이 있다.
(MyISAM은 64KB)
Barracuda 포맷에 Dynamic 또는 Compressed를 사용하면 포인터 20바이트만 저장하고 실데이터는 외부에 저장한다.
[mysqld]
innodb_file_format=barracuda
innodb_file_per_table=1
innodb 최적화
innodb_buffer_pool_size: 체섭 테이블 최대 5M정도. 인덱스 포함해도 32M면 충분?
innodb_flush_method: 기본값대로. O_DIRECT는 메모리가 커서 캐시 2중 필요 없을때만.
innodb_file_per_table: 테이블마다 독립파일로 저장
innodb_flush_log_at_trx_commit: 기본1(커밋마다), 0(로그찰때만), 추천2(1초마다)
innodb_log_file_size: 현 5M, 많이 키워도 될듯
innodb_log_buffer_size: 기본 8M 적당
innodb_thread_concurrency: 코어개수 2배 정도
sync_binlog=0 이미 꺼져있음
ib_logfile0, ib_logfile1은 로그사이즈 바꾸면 재시작이 안되므로 지우고 다시 해야함
alter table table_name engine=innodb row_format=dynamic
+202 -154
View File
@@ -1,28 +1,29 @@
<?php
namespace sammo;
function processWar(General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity){
function processWar(General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity)
{
$db = DB::db();
$attackerNationID = $attackerGeneral->getNationID();
$defenderNationID = $rawDefenderCity['nation'];
if($defenderNationID == 0){
if ($defenderNationID == 0) {
$rawDefenderNation = [
'nation'=>0,
'name'=>'재야',
'capital'=>0,
'level'=>0,
'gold'=>0,
'rice'=>10000,
'type'=>GameConst::$neutralNationType,
'tech'=>0,
'gennum'=>1
'nation' => 0,
'name' => '재야',
'capital' => 0,
'level' => 0,
'gold' => 0,
'rice' => 10000,
'type' => GameConst::$neutralNationType,
'tech' => 0,
'gennum' => 1
];
}
else{
} else {
$rawDefenderNation = $db->queryFirstRow('SELECT nation,`level`,`name`,capital,gennum,tech,`type`,gold,rice FROM nation WHERE nation = %i', $defenderNationID);
}
@@ -36,29 +37,29 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
$defenderIDList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i AND nation!=0 and crew > 0 and rice>(crew/100) and train>=defence_train and atmos>=defence_train', $city->getVar('nation'), $city->getVar('city'));
$defenderList = General::createGeneralObjListFromDB($defenderIDList, null, 2);
usort($defenderList, function(General $lhs, General $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
usort($defenderList, function (General $lhs, General $rhs) {
return - (extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
});
$iterDefender = new \ArrayIterator($defenderList);
$iterDefender->rewind();
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $rawDefenderNation, $rawDefenderCity, $db) {
if($prevDefender !== null){
$getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $rawDefenderNation, $rawDefenderCity, $db) {
if ($prevDefender !== null) {
$prevDefender->applyDB($db);
}
if(!$reqNext){
if (!$reqNext) {
return null;
}
if(!$iterDefender->valid()){
if (!$iterDefender->valid()) {
return null;
}
$nextDefender = $iterDefender->current();
$nextDefender->setRawCity($rawDefenderCity);
if(extractBattleOrder($nextDefender) <= 0){
if (extractBattleOrder($nextDefender) <= 0) {
return null;
}
@@ -82,8 +83,8 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
$updateAttackerNation = [];
$updateDefenderNation = [];
if($city->getVar('supply')){
if($city->getPhase() > 0){
if ($city->getVar('supply')) {
if ($city->getPhase() > 0) {
$rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice;
$rice *= getTechCost($rawDefenderNation['tech']);
@@ -91,12 +92,10 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
Util::setRound($rice);
$updateDefenderNation['rice'] = max(0, $rawDefenderNation['rice'] - $rice);
}
else if($conquerCity){
if($rawDefenderNation['capital'] == $rawDefenderCity['city']){
} else if ($conquerCity) {
if ($rawDefenderNation['capital'] == $rawDefenderCity['city']) {
$updateDefenderNation['rice'] = $rawDefenderNation['rice'] + 1000;
}
else{
} else {
$updateDefenderNation['rice'] = $rawDefenderNation['rice'] + 500;
}
}
@@ -120,29 +119,29 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
$attackerGenCnt_eff = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=%i AND npc != 5', $rawAttackerNation['nation']);
$defenderGenCnt_eff = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=%i AND npc != 5', $rawDefenderNation['nation']);
if($attackerGenCnt_eff < GameConst::$initialNationGenLimit){
if ($attackerGenCnt_eff < GameConst::$initialNationGenLimit) {
$attackerGenCnt = GameConst::$initialNationGenLimit;
$attackerGenCnt_eff = GameConst::$initialNationGenLimit;
}
if($defenderGenCnt_eff < GameConst::$initialNationGenLimit){
if ($defenderGenCnt_eff < GameConst::$initialNationGenLimit) {
$defenderGenCnt = GameConst::$initialNationGenLimit;
$defenderGenCnt_eff = GameConst::$initialNationGenLimit;
}
if($attackerGenCnt != $attackerGenCnt_eff){
if ($attackerGenCnt != $attackerGenCnt_eff) {
$attackerIncTech *= $attackerGenCnt / $attackerGenCnt_eff;
}
if($defenderGenCnt != $defenderGenCnt_eff){
if ($defenderGenCnt != $defenderGenCnt_eff) {
$defenderIncTech *= $defenderGenCnt / $defenderGenCnt_eff;
}
if(TechLimit($startYear, $year, $rawAttackerNation['tech'])){
if (TechLimit($startYear, $year, $rawAttackerNation['tech'])) {
$attackerIncTech /= 4;
}
if(TechLimit($startYear, $year, $rawDefenderNation['tech'])){
if (TechLimit($startYear, $year, $rawDefenderNation['tech'])) {
$defenderIncTech /= 4;
}
@@ -159,41 +158,42 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
$db->update('nation', $updateDefenderNation, 'nation=%i', $defenderNationID);
$db->update('diplomacy', [
'dead'=>$db->sqleval('dead + %i', $attacker->getDead())
'dead' => $db->sqleval('dead + %i', $attacker->getDead())
], 'me = %i and you = %i', $attackerNationID, $defenderNationID);
$db->update('diplomacy', [
'dead'=>$db->sqleval('dead + %i', $attacker->getKilled())
'dead' => $db->sqleval('dead + %i', $attacker->getKilled())
], 'me = %i and you = %i', $defenderNationID, $attackerNationID);
if(!$conquerCity){
if (!$conquerCity) {
return;
}
ConquerCity([
'startyear'=>$startYear,
'year'=>$year,
'month'=>$month,
'city_rate'=>$cityRate,
'join_mode'=>$joinMode,
'startyear' => $startYear,
'year' => $year,
'month' => $month,
'city_rate' => $cityRate,
'join_mode' => $joinMode,
], $attacker->getGeneral(), $city->getRaw());
}
function extractBattleOrder(General $general){
if($general->getVar('crew') == 0){
function extractBattleOrder(General $general)
{
if ($general->getVar('crew') == 0) {
return 0;
}
if($general->getVar('rice') <= $general->getVar('crew') / 100){
if ($general->getVar('rice') <= $general->getVar('crew') / 100) {
return 0;
}
$defence_train = $general->getVar('defence_train');
if($general->getVar('train') < $defence_train){
if ($general->getVar('train') < $defence_train) {
return 0;
}
if($general->getVar('atmos') < $defence_train){
if ($general->getVar('atmos') < $defence_train) {
return 0;
}
@@ -210,8 +210,8 @@ function processWar_NG(
callable $getNextDefender,
WarUnitCity $city,
int $relYear
):bool{
$templates = new \League\Plates\Engine(__DIR__.'/templates');
): bool {
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
$logger = $attacker->getLogger();
@@ -231,11 +231,14 @@ function processWar_NG(
$logger->pushGlobalActionLog("<D><b>{$attacker->getNationVar('name')}</b></>의 <Y>{$attacker->getName()}</>{$josaYi} <G><b>{$city->getName()}</b></>{$josaRo} 진격합니다.");
$logger->pushGeneralActionLog("<G><b>{$city->getName()}</b></>{$josaRo} <M>진격</>합니다. <1>$date</>");
for($currPhase = 0; $currPhase < $attacker->getMaxPhase(); $currPhase+=1){
if($defender === null){
$logWritten = false;
while($attacker->getPhase() < $attacker->getMaxPhase()){
$logWritten = false;
if ($defender === null) {
$defender = $city;
if($city->getNationVar('rice') <= 0 && $city->getVar('supply')){
if ($city->getNationVar('rice') <= 0 && $city->getVar('supply')) {
//병량 패퇴
$attacker->setOppose($defender);
$defender->setOppose($attacker);
@@ -256,8 +259,8 @@ function processWar_NG(
}
}
if($defender->getPhase() == 0){
$defender->setPrePhase($currPhase);
if ($defender->getPhase() == 0 && $defender->getOppose() == null) {
$defender->setPrePhase($attacker->getPhase());
$attacker->addTrain(1);
$defender->addTrain(1);
@@ -266,17 +269,17 @@ function processWar_NG(
$defenderCrewTypeCoef = $defender->getCrewType()->getAttackCoef($attacker->getCrewType()) * $attacker->getCrewType()->getDefenceCoef($defender->getCrewType());
/*
if($attackerCrewTypeCoef > $defenderCrewTypeCoef && $attacker instanceof WarUnitGeneral){
$attacker->getGeneral()->increaseInheritancePoint('snipe_combat', 1);
$attacker->getGeneral()->increaseInheritancePoint(InheritanceKey::snipe_combat, 1);
}
if($defenderCrewTypeCoef > $attackerCrewTypeCoef && $defender instanceof WarUnitGeneral){
$defender->getGeneral()->increaseInheritancePoint('snipe_combat', 1);
$defender->getGeneral()->increaseInheritancePoint(InheritanceKey::snipe_combat, 1);
}
*/
$attackerName = $attacker->getName();
$attackerCrewTypeName = $attacker->getCrewTypeName();
if($defender instanceof WarUnitGeneral){
if ($defender instanceof WarUnitGeneral) {
$defenderName = $defender->getName();
$defenderCrewTypeName = $defender->getCrewTypeName();
@@ -291,8 +294,7 @@ function processWar_NG(
$josaRo = JosaUtil::pick($defenderCrewTypeName, '로');
$josaUl = JosaUtil::pick($attackerCrewTypeName, '을');
$defender->getLogger()->pushGeneralActionLog("{$defenderCrewTypeName}{$josaRo} <Y>{$attackerName}</>의 {$attackerCrewTypeName}{$josaUl} <M>수비</>합니다.");
}
else{
} else {
$josaYi = JosaUtil::pick($attackerName, '이');
$josaRo = JosaUtil::pick($attackerCrewTypeName, '로');
$logger->pushGlobalActionLog("<Y>{$attackerName}</>{$josaYi} {$attackerCrewTypeName}{$josaRo} 성벽을 공격합니다.");
@@ -324,16 +326,15 @@ function processWar_NG(
$attackerHP = $attacker->getHP();
$defenderHP = $defender->getHP();
if($deadAttacker > $attackerHP || $deadDefender > $defenderHP){
if ($deadAttacker > $attackerHP || $deadDefender > $defenderHP) {
$deadAttackerRatio = $deadAttacker / max(1, $attackerHP);
$deadDefenderRatio = $deadDefender / max(1, $defenderHP);
if($deadDefenderRatio > $deadAttackerRatio){
if ($deadDefenderRatio > $deadAttackerRatio) {
//수비자가 더 병력 부족
$deadAttacker /= $deadDefenderRatio;
$deadDefender = $defenderHP;
}
else{
} else {
//공격자가 더 병력 부족
$deadDefender /= $deadAttackerRatio;
$deadAttacker = $attackerHP;
@@ -349,15 +350,22 @@ function processWar_NG(
$attacker->increaseKilled($deadDefender);
$defender->increaseKilled($deadAttacker);
$phaseNickname = $currPhase + 1;
if($defender->getPhase() < 0){
$phaseNickname = '先';
}
else{
$currPhase = $attacker->getPhase() + 1;
$phaseNickname = "{$currPhase} ";
}
if($deadAttacker > 0 || $deadDefender > 0){
if ($deadAttacker > 0 || $deadDefender > 0) {
$attacker->getLogger()->pushGeneralBattleDetailLog(
"$phaseNickname : <Y1>【{$attacker->getName()}】</> <C>{$attacker->getHP()} (-$deadAttacker)</> VS <C>{$defender->getHP()} (-$deadDefender)</> <Y1>【{$defender->getName()}】</>"
"$phaseNickname: <Y1>【{$attacker->getName()}】</> <C>{$attacker->getHP()} (-$deadAttacker)</> VS <C>{$defender->getHP()} (-$deadDefender)</> <Y1>【{$defender->getName()}】</>"
);
$defender->getLogger()->pushGeneralBattleDetailLog(
"$phaseNickname : <Y1>【{$defender->getName()}】</> <C>{$defender->getHP()} (-$deadDefender)</> VS <C>{$attacker->getHP()} (-$deadAttacker)</> <Y1>【{$attacker->getName()}】</>"
"$phaseNickname: <Y1>【{$defender->getName()}】</> <C>{$defender->getHP()} (-$deadDefender)</> VS <C>{$attacker->getHP()} (-$deadAttacker)</> <Y1>【{$attacker->getName()}】</>"
);
}
@@ -365,7 +373,9 @@ function processWar_NG(
$attacker->addPhase();
$defender->addPhase();
if(!$attacker->continueWar($noRice)){
if (!$attacker->continueWar($noRice)) {
$logWritten = true;
$attacker->logBattleResult();
$defender->logBattleResult();
@@ -377,10 +387,9 @@ function processWar_NG(
$josaYi = JosaUtil::pick($attacker->getCrewTypeName(), '이');
$logger->pushGlobalActionLog("<Y>{$attacker->getName()}</>의 {$attacker->getCrewTypeName()}{$josaYi} 퇴각했습니다.");
if($noRice){
if ($noRice) {
$attacker->getLogger()->pushGeneralActionLog("군량 부족으로 퇴각합니다.", ActionLogger::PLAIN);
}
else{
} else {
$attacker->getLogger()->pushGeneralActionLog("퇴각했습니다.", ActionLogger::PLAIN);
}
$defender->getLogger()->pushGeneralActionLog("<Y>{$attacker->getName()}</>의 {$attacker->getCrewTypeName()}{$josaYi} 퇴각했습니다.", ActionLogger::PLAIN);
@@ -388,7 +397,8 @@ function processWar_NG(
break;
}
if(!$defender->continueWar($noRice)){
if (!$defender->continueWar($noRice)) {
$logWritten = true;
$attacker->logBattleResult();
$defender->logBattleResult();
@@ -399,7 +409,7 @@ function processWar_NG(
$attacker->tryWound();
$defender->tryWound();
if($defender === $city){
if ($defender === $city) {
$attacker->addLevelExp(1000);
$conquerCity = true;
break;
@@ -407,33 +417,30 @@ function processWar_NG(
$josaYi = JosaUtil::pick($defender->getCrewTypeName(), '이');
if($noRice){
if ($noRice) {
$logger->pushGlobalActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.");
$attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.", ActionLogger::PLAIN);
$attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.", ActionLogger::PLAIN);
$defender->getLogger()->pushGeneralActionLog("군량 부족으로 패퇴합니다.", ActionLogger::PLAIN);
}
else{
} else {
$logger->pushGlobalActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 전멸했습니다.");
$attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 전멸했습니다.", ActionLogger::PLAIN);
$attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 전멸했습니다.", ActionLogger::PLAIN);
$defender->getLogger()->pushGeneralActionLog("전멸했습니다.", ActionLogger::PLAIN);
}
if($currPhase + 1 == $attacker->getMaxPhase()){
if ($attacker->getPhase() >= $attacker->getMaxPhase()) {
break;
}
$defender->finishBattle();
$defender = ($getNextDefender)($defender, true);
if($defender !== null && !($defender instanceof WarUnitGeneral)){
if ($defender !== null && !($defender instanceof WarUnitGeneral)) {
throw new \RuntimeException('다음 수비자를 받아오는데 실패');
}
}
}
if($currPhase == $attacker->getMaxPhase()){
if (!$logWritten) {
//마지막 페이즈의 전투 마무리
$attacker->logBattleResult();
$defender->logBattleResult();
@@ -445,9 +452,9 @@ function processWar_NG(
$attacker->finishBattle();
$defender->finishBattle();
if($defender instanceof WarUnitCity){
if ($defender instanceof WarUnitCity) {
$newConflict = $defender->addConflict();
if($newConflict){
if ($newConflict) {
$nationName = $attacker->getNationVar('name');
$josaYi = JosaUtil::pick($nationName, '이');
$logger->pushGlobalHistoryLog("<M><b>【분쟁】</b></><D><b>{$nationName}</b></>{$josaYi} <G><b>{$defender->getName()}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다.");
@@ -459,33 +466,36 @@ function processWar_NG(
return $conquerCity;
}
function DeleteConflict($nation) {
function DeleteConflict($nation)
{
$db = DB::db();
foreach($db->queryAllLists('SELECT city, conflict FROM city WHERE conflict!=%s', '{}') as list($cityID, $rawConflict)){
foreach ($db->queryAllLists('SELECT city, conflict FROM city WHERE conflict!=%s', '{}') as list($cityID, $rawConflict)) {
$conflict = Json::decode($rawConflict);
if(!$conflict || !is_array($conflict)){
if (!$conflict || !is_array($conflict)) {
continue;
}
if(!key_exists($nation, $conflict)){
if (!key_exists($nation, $conflict)) {
continue;
}
unset($conflict[$nation]);
$db->update('city', [
'conflict'=>Json::encode($conflict)
'conflict' => Json::encode($conflict)
], 'city=%i', $cityID);
}
}
function getConquerNation($city) : int {
function getConquerNation($city): int
{
$conflict = Json::decode($city['conflict']);
return Util::array_first_key($conflict);
}
function ConquerCity(array $admin, General $general, array $city) {
function ConquerCity(array $admin, General $general, array $city)
{
$db = DB::db();
$year = $admin['year'];
@@ -506,7 +516,7 @@ function ConquerCity(array $admin, General $general, array $city) {
$defenderNationLogger = new ActionLogger(0, $defenderNationID, $year, $month);
if($defenderNationID) {
if ($defenderNationID) {
$defenderNationDecoration = "<D><b>{$defenderNationName}</b></>의";
} else {
$defenderNationDecoration = "공백지인";
@@ -524,8 +534,29 @@ function ConquerCity(array $admin, General $general, array $city) {
$defenderNationLogger->pushNationalHistoryLog("<D><b>{$attackerNationName}</b></>의 <Y>{$attackerGeneralName}</>에 의해 <G><b>{$cityName}</b></>{$josaYiCity} <O>함락</>");
$gameStor = KVStorage::getStorage($db, 'game_env');
// 이벤트 핸들러 동작
$e_env = null;
foreach (DB::db()->query('SELECT * FROM event WHERE target = "OCCUPY_CITY" ORDER BY `priority` DESC, `id` ASC') as $rawEvent) {
if ($e_env === null) {
$e_env = $gameStor->getAll(false);
}
$eventID = $rawEvent['id'];
$cond = Json::decode($rawEvent['condition']);
$action = Json::decode($rawEvent['action']);
$event = new Event\EventHandler($cond, $action);
$e_env['currentEventID'] = $eventID;
$event->tryRunEvent($e_env);
}
if ($e_env !== null) {
$gameStor->resetCache();
}
// 국가 멸망시
if($defenderNationID && $db->queryFirstField('SELECT count(city) FROM city WHERE nation = %i', $defenderNationID) === 1) {
if ($defenderNationID && $db->queryFirstField('SELECT count(city) FROM city WHERE nation = %i', $defenderNationID) === 1) {
$defenderNationLogger->flush();
unset($defenderNationLogger);
@@ -545,17 +576,17 @@ function ConquerCity(array $admin, General $general, array $city) {
$loseGeneralGold = 0;
$loseGeneralRice = 0;
foreach($oldNationGenerals as $oldGeneral){
$loseGold = intdiv($oldGeneral->getVar('gold') * (rand()%30+20), 100);
$loseRice = intdiv($oldGeneral->getVar('rice') * (rand()%30+20), 100);
foreach ($oldNationGenerals as $oldGeneral) {
$loseGold = intdiv($oldGeneral->getVar('gold') * (rand() % 30 + 20), 100);
$loseRice = intdiv($oldGeneral->getVar('rice') * (rand() % 30 + 20), 100);
$oldGeneral->getLogger()->pushGeneralActionLog(
"도주하며 금<C>$loseGold</> 쌀<C>$loseRice</>을 분실했습니다.",
ActionLogger::PLAIN
);
$oldGeneral->increaseVar('gold', -$loseGold);
$oldGeneral->increaseVar('rice', -$loseRice);
$oldGeneral->addExperience(-$oldGeneral->getVar('experience')*0.1, false);
$oldGeneral->addDedication(-$oldGeneral->getVar('dedication')*0.5, false);
$oldGeneral->addExperience(-$oldGeneral->getVar('experience') * 0.1, false);
$oldGeneral->addDedication(-$oldGeneral->getVar('dedication') * 0.5, false);
$loseGeneralGold += $loseGold;
$loseGeneralRice += $loseRice;
@@ -563,21 +594,21 @@ function ConquerCity(array $admin, General $general, array $city) {
$oldGeneral->applyDB($db);
//모두 등용장 발부
if($admin['join_mode'] != 'onlyRandom' && Util::randBool(0.5)) {
if ($admin['join_mode'] != 'onlyRandom' && Util::randBool(0.5)) {
$msg = ScoutMessage::buildScoutMessage($attackerID, $oldGeneral->getID());
if($msg){
if ($msg) {
$msg->send(true);
}
}
//NPC인 경우 일정 확률로 임관(엔장, 인재, 의병)
$npcType = $oldGeneral->getNPCType();
if($admin['join_mode'] != 'onlyRandom' && 2 <= $npcType && $npcType <= 8 && $npcType != 5 && Util::randBool(GameConst::$joinRuinedNPCProp)) {
if ($admin['join_mode'] != 'onlyRandom' && 2 <= $npcType && $npcType <= 8 && $npcType != 5 && Util::randBool(GameConst::$joinRuinedNPCProp)) {
$cmd = buildGeneralCommandClass('che_임관', $oldGeneral, $admin, [
'destNationID'=>$attackerNationID
'destNationID' => $attackerNationID
]);
$joinTurn = Util::randRangeInt(0, 12);
if($joinTurn){
if ($joinTurn) {
_setGeneralCommand(buildGeneralCommandClass('che_견문', $oldGeneral, $admin), iterator_to_array(Util::range($joinTurn)));
}
_setGeneralCommand($cmd, [$joinTurn]);
@@ -596,37 +627,56 @@ function ConquerCity(array $admin, General $general, array $city) {
// 기본량 제외 금쌀50% + 장수들 분실 금쌀50% 흡수
$db->update('nation', [
'gold'=>$db->sqleval('gold + %i', $loseNationGold),
'rice'=>$db->sqleval('rice + %i', $loseNationRice),
'gold' => $db->sqleval('gold + %i', $loseNationGold),
'rice' => $db->sqleval('rice + %i', $loseNationRice),
], 'nation=%i', $attackerNationID);
//아국 수뇌부에게 로그 전달
$loseNationGoldText = number_format($loseNationGold);
$loseNationRiceText = number_format($loseNationRice);
$resourceLog = "<D><b>{$defenderNationName}</b></> 정복으로 금<C>{$loseNationGoldText}</> 쌀<C>{$loseNationRiceText}</>을 획득했습니다.";
foreach($db->queryFirstColumn(
'SELECT no FROM general WHERE nation=%i AND officer_level>=5', $attackerNationID
) as $attackerChiefID
){
if($attackerChiefID == $attackerID){
foreach ($db->queryFirstColumn(
'SELECT no FROM general WHERE nation=%i AND officer_level>=5',
$attackerNationID
) as $attackerChiefID) {
if ($attackerChiefID == $attackerID) {
$attackerLogger->pushGeneralActionLog($resourceLog, ActionLogger::PLAIN);
}
else{
} else {
$chiefLogger = new ActionLogger($attackerChiefID, $attackerNationID, $year, $month);
$chiefLogger->pushGeneralActionLog($resourceLog, ActionLogger::PLAIN);
$chiefLogger->flush();
}
}
// 멸망이 아니면
// 이벤트 핸들러 동작
$e_env = null;
foreach (DB::db()->query('SELECT * FROM event WHERE target = "DESTROY_NATION" ORDER BY `priority` DESC, `id` ASC') as $rawEvent) {
if ($e_env === null) {
$e_env = $gameStor->getAll(false);
}
$eventID = $rawEvent['id'];
$cond = Json::decode($rawEvent['condition']);
$action = Json::decode($rawEvent['action']);
$event = new Event\EventHandler($cond, $action);
$e_env['currentEventID'] = $eventID;
$event->tryRunEvent($e_env);
}
if ($e_env !== null) {
$gameStor->resetCache();
}
// 멸망이 아니면
} else {
// 태수,군사,종사은 일반으로...
$db->update('general',[
'officer_level'=>1,
'officer_city'=>0,
], 'officer_city = %i',$cityID);
$db->update('general', [
'officer_level' => 1,
'officer_city' => 0,
], 'officer_city = %i', $cityID);
//수도였으면 긴급 천도
if($defenderNationID && $defenderStaticNation['capital'] == $cityID) {
if ($defenderNationID && $defenderStaticNation['capital'] == $cityID) {
$minCity = findNextCapital($cityID, $defenderNationID);
$minCityName = CityConst::byID($minCity)->name;
@@ -636,10 +686,10 @@ function ConquerCity(array $admin, General $general, array $city) {
$moveLog = "수도가 함락되어 <G><b>$minCityName</b></>으로 <M>긴급천도</>합니다.";
//아국 수뇌부에게 로그 전달
foreach($db->queryFirstColumn(
'SELECT no FROM general WHERE nation=%i AND officer_level>=5', $defenderNationID
) as $defenderChiefID
){
foreach ($db->queryFirstColumn(
'SELECT no FROM general WHERE nation=%i AND officer_level>=5',
$defenderNationID
) as $defenderChiefID) {
$chiefLogger = new ActionLogger($defenderChiefID, $defenderNationID, $year, $month);
$chiefLogger->pushGeneralActionLog($moveLog, ActionLogger::PLAIN);
$chiefLogger->flush();
@@ -647,22 +697,22 @@ function ConquerCity(array $admin, General $general, array $city) {
//천도
$db->update('nation', [
'capital'=>$minCity,
'gold'=>$db->sqleval('gold * 0.5'),
'rice'=>$db->sqleval('rice * 0.5'),
'capital' => $minCity,
'gold' => $db->sqleval('gold * 0.5'),
'rice' => $db->sqleval('rice * 0.5'),
], 'nation=%i', $defenderNationID);
//보급도시로 만듬
$db->update('city', [
'supply'=>1
'supply' => 1
], 'city=%i', $minCity);
//수뇌부 이동
$db->update('general', [
'city'=>$minCity
], 'nation=%i AND officer_level>=5',$defenderNationID);
'city' => $minCity
], 'nation=%i AND officer_level>=5', $defenderNationID);
//장수 사기 감소
$db->update('general', [
'atmos'=>$db->sqleval('atmos*0.8')
], 'nation=%i',$defenderNationID);
'atmos' => $db->sqleval('atmos*0.8')
], 'nation=%i', $defenderNationID);
refreshNationStaticInfo();
}
@@ -673,10 +723,9 @@ function ConquerCity(array $admin, General $general, array $city) {
if ($conquerNation == $attackerNationID) {
// 이동
$db->update('general', [
'city'=>$cityID
'city' => $cityID
], 'no=%i', $attackerID);
}
else{
} else {
$conquerNationName = getNationStaticInfo($conquerNation)['name'];
$conquerNationLogger = new ActionLogger(0, $conquerNation, $year, $month);
@@ -690,16 +739,16 @@ function ConquerCity(array $admin, General $general, array $city) {
}
$query = [
'supply'=>1,
'term'=>0,
'conflict'=>'{}',
'agri'=>$db->sqleval('agri*0.7'),
'comm'=>$db->sqleval('comm*0.7'),
'secu'=>$db->sqleval('secu*0.7'),
'nation'=>$conquerNation,
'officer_set'=>0,
'supply' => 1,
'term' => 0,
'conflict' => '{}',
'agri' => $db->sqleval('agri*0.7'),
'comm' => $db->sqleval('comm*0.7'),
'secu' => $db->sqleval('secu*0.7'),
'nation' => $conquerNation,
'officer_set' => 0,
];
if($city['level'] > 3) {
if ($city['level'] > 3) {
$query['def'] = 1000;
$query['wall'] = 1000;
} else {
@@ -717,45 +766,44 @@ function ConquerCity(array $admin, General $general, array $city) {
$nearNationsID[] = $conquerNation;
$nearNationsID = array_unique($nearNationsID);
foreach($nearNationsID as $nationNationID){
foreach ($nearNationsID as $nationNationID) {
SetNationFront($nationNationID);
}
}
function findNextCapital(int $capitalID, int $nationID):int{
function findNextCapital(int $capitalID, int $nationID): int
{
$distList = searchDistance($capitalID, 99, true);
$cities = [];
foreach(
DB::db()->query(
foreach (DB::db()->query(
'SELECT city, pop FROM city WHERE nation=%i and city!=%i',
$nationID,
$capitalID
) as $row
){
) as $row) {
$cities[$row['city']] = $row['pop'];
};
foreach($distList as $dist=>$distSubList){
foreach ($distList as $dist => $distSubList) {
$maxCityPop = 0;
$minCity = 0;
foreach($distSubList as $cityID){
if(!key_exists($cityID, $cities)){
foreach ($distSubList as $cityID) {
if (!key_exists($cityID, $cities)) {
continue;
}
$cityPop = $cities[$cityID];
if($cityPop < $maxCityPop){
if ($cityPop < $maxCityPop) {
continue;
}
$minCity = $cityID;
$maxCityPop = $cityPop;
}
if($minCity){
if ($minCity) {
return $minCity;
}
}
throw new \RuntimeException('도시가 남지 않았는데 긴천을 시도하고 있습니다');
}
}
-4
View File
@@ -1,4 +0,0 @@
<?php
require('../vendor/autoload.php');
//ParsedownExtra;
+4 -2
View File
@@ -16,8 +16,10 @@ include "func.php";
<title>최근 지도</title>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printStaticValues([
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID
'staticValues' => [
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID
],
]) ?>
<?= WebUtil::printJS('d_shared/base_map.js') ?>
+63
View File
@@ -0,0 +1,63 @@
<?php
namespace sammo\API\Betting;
use sammo\Session;
use DateTimeInterface;
use sammo\Betting;
use sammo\DB;
use sammo\DTO\BettingItem;
use sammo\Validator;
use sammo\GameConst;
use sammo\KVStorage;
use sammo\UserLogger;
use sammo\Util;
class Bet extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('required', [
'bettingID',
'bettingType',
'amount'
])
->rule('integer', 'bettingID')
->rule('integerArray', 'bettingType')
->rule('integer', 'amount')
->rule('min', 'amount', 1);
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
/** @var int */
$bettingID = $this->args['bettingID'];
/** @var int[] */
$bettingType = $this->args['bettingType'];
/** @var int */
$amount = $this->args['amount'];
$bettingHelper = new Betting($bettingID);
try{
$bettingHelper->bet($session->generalID, $session->userID, $bettingType, $amount);
}
catch(\Throwable $e){
return $e->getMessage();
}
return [
'result' => true
];
}
}
@@ -0,0 +1,94 @@
<?php
namespace sammo\API\Betting;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\DTO\BettingInfo;
use sammo\KVStorage;
use sammo\Util;
use sammo\Validator;
class GetBettingDetail extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('required', [
'betting_id',
])
->rule('integer', 'betting_id');
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$db = DB::db();
/** @var int */
$bettingID = $this->args['betting_id'];
$gameStor = KVStorage::getStorage($db, 'game_env');
$bettingStor = KVStorage::getStorage($db, 'betting');
$rawBettingInfo = $bettingStor->getValue("id_{$bettingID}");
if($rawBettingInfo === null){
return '해당 베팅이 없습니다';
}
try{
$bettingInfo = new BettingInfo($rawBettingInfo);
}
catch(\Error $e){
return $e->getMessage();
}
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$bettingDetail = [];
foreach ($db->queryAllLists(
'SELECT betting_type, sum(amount) as sum_amount FROM ng_betting WHERE betting_id = %i GROUP BY betting_type',
$bettingID
) as [$bettingType, $amount]) {
$bettingDetail[] = [$bettingType, Util::toInt($amount)];
}
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$myBetting = [];
foreach($db->queryAllLists(
'SELECT betting_type, sum(amount) as sum_amount FROM ng_betting WHERE betting_id = %i AND user_id = %i GROUP BY betting_type',
$bettingID, $session->userID
) as [$bettingType, $amount]){
$myBetting[] = [$bettingType, Util::toInt($amount)];
}
if($bettingInfo->reqInheritancePoint){
$inheritStor = KVStorage::getStorage($db, "inheritance_{$session->userID}");
$remainPoint = ($inheritStor->getValue('previous') ?? [0,0])[0];
}
else{
$remainPoint = $db->queryFirstField('SELECT gold FROM general WHERE no = %i', $session->generalID)??0;
}
return [
'result' => true,
'bettingInfo' => $rawBettingInfo,
'bettingDetail' => $bettingDetail,
'myBetting' => $myBetting,
'remainPoint' => $remainPoint,
'year' => $year,
'month' => $month,
];
}
}
+92
View File
@@ -0,0 +1,92 @@
<?php
namespace sammo\API\Betting;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\DTO\BettingInfo;
use sammo\KVStorage;
use sammo\Validator;
use function sammo\checkLimit;
use function sammo\increaseRefresh;
class GetBettingList extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('in', 'req', ['bettingNation', 'tournament']);
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$db = DB::db();
$reqType = $this->args['req'] ?? null;
increaseRefresh("베팅장", 1);
$gameStor = KVStorage::getStorage($db, 'game_env');
$bettingStor = KVStorage::getStorage($db, 'betting');
$userID = $session->userID;
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,penalty,permission FROM general WHERE owner=%i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
return "접속 제한중입니다.";
}
$bettingList = [];
foreach ($bettingStor->getAll() as $_key => $rawItem) {
$item = new BettingInfo($rawItem);
if ($reqType !== null && $item->type != $reqType) {
continue;
}
unset($rawItem['candidates']);
$bettingList[$item->id] = $rawItem;
$bettingList[$item->id]['totalAmount'] = 0;
}
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
if (!$bettingList) {
return [
'result' => true,
'bettingList' => $bettingList,
'year' => $year,
'month' => $month,
];
}
$bettingIDList = array_keys($bettingList);
// XXX: query cache만 믿고 sum을 하는 짓을 벌여도 되는가?
foreach ($db->queryAllLists(
'SELECT betting_id, sum(amount) as total_amount FROM ng_betting WHERE betting_id IN %li GROUP BY betting_id',
$bettingIDList
) as [$bettingID, $totalAmount]) {
if (!key_exists($bettingID, $bettingList)) {
continue;
}
$bettingList[$bettingID]['totalAmount'] = $totalAmount;
}
return [
'result' => true,
'bettingList' => $bettingList,
'year' => $year,
'month' => $month,
];
}
}
-1
View File
@@ -6,7 +6,6 @@ use sammo\Session;
use DateTimeInterface;
use sammo\Validator;
use function sammo\cutTurn;
use function sammo\pushGeneralCommand;
class PushCommand extends \sammo\BaseAPI
-1
View File
@@ -6,7 +6,6 @@ use sammo\Session;
use DateTimeInterface;
use sammo\Validator;
use function sammo\cutTurn;
use function sammo\repeatGeneralCommand;
class RepeatCommand extends \sammo\BaseAPI
@@ -0,0 +1,76 @@
<?php
namespace sammo\API\Command;
use sammo\Session;
use DateTimeInterface;
use sammo\GameConst;
use sammo\Util;
use sammo\Validator;
use function sammo\setGeneralCommand;
class ReserveBulkCommand extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
foreach ($this->args as $idx => $turn) {
$v = new Validator($turn);
$v->rule('required', [
'action',
'turnList'
])
->rule('lengthMin', 'action', 1)
->rule('integerArray', 'turnList');
if (!$v->validate()) {
return "{$idx}:{$v->errorStr()}";
}
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$briefList = [];
foreach ($this->args as $idx => $turn) {
$action = $turn['action'];
$turnList = $turn['turnList'];
$arg = $turn['arg'] ?? [];
if (!$turnList) {
return "{$idx}: 턴이 입력되지 않았습니다";
}
if (!in_array($action, Util::array_flatten(GameConst::$availableGeneralCommand))) {
return "{$idx}: 사용할 수 없는 커맨드입니다.";
}
if (!is_array($arg)) {
return "{$idx}: 올바른 arg 형태가 아닙니다.";
}
$partialResult = setGeneralCommand($session->generalID, $turnList, $action, $arg);
if(!$partialResult['result']){
return [
'result' => false,
'briefList' => $briefList,
'errorIdx' => $idx,
'reason' => $partialResult['reason']
];
}
$briefList[$idx] = $partialResult['brief'];
}
return [
'result' => true,
'briefList' => $briefList,
'reason' => 'success'
];
}
}
+68
View File
@@ -0,0 +1,68 @@
<?php
namespace sammo\API\General;
use sammo\DB;
use sammo\Validator;
use sammo\Session;
use sammo\GameConst;
use sammo\General;
use sammo\JosaUtil;
class DropItem extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('required', [
'itemType',
])
->rule('in', 'itemType', array_keys(GameConst::$allItems));
if (!$v->validate()) {
return "{$v->errorStr()}";
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$generalID = $session->generalID;
$me = General::createGeneralObjFromDB($generalID);
$itemType = $this->args['itemType'];
$item = $me->getItem($itemType);
if ($item->getRawClassName() === 'None') {
return '아이템을 가지고 있지 않습니다.';
}
$me->setItem($itemType, 'None');
$logger = $me->getLogger();
$generalName = $me->getName();
$josaYi = JosaUtil::pick($generalName, '이');
$itemName = $item->getName();
$itemRawName = $item->getRawName();
$josaUl = JosaUtil::pick($itemRawName, '을');
$logger->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 버렸습니다.");
$nationName = $me->getStaticNation()['name'];
if (!$item->isBuyable()) {
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 잃었습니다!");
$logger->pushGlobalHistoryLog("<R><b>【망실】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 잃었습니다!");
}
$me->applyDB(DB::db());
return null;
}
}
+51
View File
@@ -0,0 +1,51 @@
<?php
namespace sammo\API\General;
use sammo\Validator;
use sammo\API\Nation\GetGeneralLog as GetNationGeneralLog;
use sammo\Session;
class GetGeneralLog extends GetNationGeneralLog
{
const GENERAL_HISTORY = 'generalHistory';
const GENERAL_ACTION = 'generalAction';
const BATTLE_RESULT = 'battleResult';
const BATTLE_DETAIL = 'battleDetail';
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v
->rule('required', [
'type',
])
->rule('integer', [
'reqTo',
])
->rule('in', 'type', [
self::GENERAL_HISTORY,
self::GENERAL_ACTION,
self::BATTLE_RESULT,
self::BATTLE_DETAIL,
]);
if (!$v->validate()) {
return $v->errorStr();
}
if (key_exists('reqTo', $this->args)) {
$this->args['reqTo'] = (int)$this->args['reqTo'];
}
return null;
}
public function checkPermission(array $me): ?string
{
return null;
}
public function getTargetGeneralID(Session $session): int{
return $session->generalID;
}
}
+9 -7
View File
@@ -5,9 +5,11 @@ namespace sammo\API\General;
use sammo\ActionLogger;
use sammo\CityConst;
use sammo\DB;
use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\GameUnitConst;
use sammo\General;
use sammo\InheritancePointManager;
use sammo\JosaUtil;
use sammo\Json;
use sammo\KVStorage;
@@ -26,7 +28,6 @@ use function sammo\cutTurn;
use function sammo\getGeneralSpecialWarName;
use function sammo\getRandTurn;
use function sammo\pushAdminLog;
use function sammo\applyInheritanceUser;
class Join extends \sammo\BaseAPI
{
@@ -155,7 +156,8 @@ class Join extends \sammo\BaseAPI
$admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year', 'month']);
$inheritTotalPoint = applyInheritanceUser($userID);
$inheritPointManager = InheritancePointManager::getInstance();
$inheritTotalPoint = $inheritPointManager->applyInheritanceUser($userID);
$inheritRequiredPoint = 0;
$userLogger = new UserLogger($userID, $admin['year'], $admin['month'], false);
@@ -368,18 +370,15 @@ class Join extends \sammo\BaseAPI
$db->insert('general_turn', $turnRows);
$rank_data = [];
foreach (array_keys(General::RANK_COLUMN) as $rankColumn) {
foreach (RankColumn::cases() as $rankColumn) {
$rank_data[] = [
'general_id' => $generalID,
'nation_id' => 0,
'type' => $rankColumn,
'type' => $rankColumn->value,
'value' => 0
];
}
$db->insert('rank_data', $rank_data);
$db->insert('betting', [
'general_id' => $generalID,
]);
$cityname = CityConst::byID($city)->name;
@@ -388,6 +387,9 @@ class Join extends \sammo\BaseAPI
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}");
$inheritStor->setValue('previous', [$inheritTotalPoint - $inheritRequiredPoint, null]);
$userLogger->flush();
$db->update('rank_data', [
'value'=>$db->sqleval('value + %i', $inheritRequiredPoint)
], 'general_id = %i AND type = %s', $generalID, RankColumn::inherit_point_spent_dynamic->value);
}
$me = [
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use sammo\TurnExecutionHelper;
class ExecuteEngine extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
return null;
}
public function getRequiredSessionMode(): int
{
return static::NO_SESSION;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$updated = TurnExecutionHelper::executeAllCommand();
return [
'result' => true,
'updated' => $updated,
];
}
}
+154
View File
@@ -0,0 +1,154 @@
<?php
namespace sammo\API\Global;
use sammo\DB;
use sammo\Json;
use sammo\KVStorage;
use sammo\RootDB;
use sammo\Session;
use function sammo\calcLeadershipBonus;
use function sammo\checkLimit;
use function sammo\getDed;
use function sammo\getExpLevel;
use function sammo\getGenChar;
use function sammo\getGeneralSpecialDomesticName;
use function sammo\getGeneralSpecialWarName;
use function sammo\getHonor;
use function sammo\getNationStaticInfo;
use function sammo\getOfficerLevelText;
use function sammo\increaseRefresh;
class GeneralList extends \sammo\BaseAPI
{
static $withToken = false;
public function validateArgs(): ?string
{
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_LOGIN;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$userID = $session->userID;
if ($session->isGameLoggedIn()) {
increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.';
}
} else {
$availableNextCall = $session->availableNextCallGetGeneralList ?? '2000-01-01 00:00:00';
$now = new \DateTimeImmutable();
if ($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5) {
return "장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : " . $availableNextCall;
}
$availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s');
$session->availableNextCallGetGeneralList = $availableNextCall;
}
$session->setReadOnly();
$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general');
$ownerNameList = [];
if ($gameStor->isunited) {
foreach (RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]) {
$ownerNameList[$ownerID] = $ownerName;
}
}
$generalList = [];
foreach ($rawGeneralList as $rawGeneral) {
[$owner, $no, $picture, $imgsvr, $npc, $age, $nation, $special, $special2, $personal, $name, $ownerName, $injury, $leadership, $strength, $intel, $experience, $dedication, $officerLevel, $killturn, $connectCnt] = $rawGeneral;
if (key_exists($owner, $ownerNameList)) {
$ownerName = $ownerNameList[$owner];
}
$nationArr = getNationStaticInfo($nation);
$lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']);
$generalList[] = [
$no,
$picture,
$imgsvr,
$npc,
$age,
$nationArr['name'],
getGeneralSpecialDomesticName($special),
getGeneralSpecialWarName($special2),
getGenChar($personal),
$name,
$npc == 1 ? $ownerName : null,
$injury,
$leadership,
$lbonus,
$strength,
$intel,
getExpLevel($experience),
getHonor($experience),
getDed($dedication),
getOfficerLevelText($officerLevel, $nationArr['level']),
$killturn,
$connectCnt
];
}
$resultColumns = [
'no',
'picture',
'imgsvr',
'npc',
'age',
'nationName',
'special',
'special2',
'personal',
'name',
'ownerName',
'injury',
'leadership',
'lbonus',
'strength',
'intel',
'explevel',
'honorText',
'dedLevelText',
'officerLevelText',
];
$result = [
'result' => 'true',
'column' => $resultColumns,
'list' => $generalList,
];
if (static::$withToken) {
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
$tokens = [];
foreach ($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token) {
$validUntil = $token['valid_until'];
foreach (Json::decode($token['pick_result']) as $pickResult) {
$tokens[$pickResult['no']] = $pickResult['keepCnt'];
}
}
$result['token'] = $tokens;
}
return $result;
}
}
@@ -0,0 +1,8 @@
<?php
namespace sammo\API\Global;
class GeneralListWithToken extends GeneralList
{
static $withToken = true;
}
+101
View File
@@ -0,0 +1,101 @@
<?php
namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use Nette\Caching\Cache;
use sammo\APICacheResult;
use sammo\GameConst;
use sammo\MapRequest;
use sammo\TimeUtil;
use sammo\UniqueConst;
use sammo\Util;
use sammo\Validator;
use function sammo\getGlobalHistoryLogRecent;
use function sammo\getWorldMap;
use function sammo\prepareDir;
class GetCachedMap extends \sammo\BaseAPI
{
const CACHE_SECONDS = 600;
private ?\DateTimeInterface $cachedTime = null;
public function validateArgs(): ?string
{
return null;
}
public function tryCache(): ?APICacheResult
{
if ($this->cachedTime === null) {
return null;
}
$now = TimeUtil::nowDateTimeImmutable();
$diff = TimeUtil::DateIntervalToSeconds($this->cachedTime->diff($now));
$nextCacheTime = self::CACHE_SECONDS - $diff;
return new APICacheResult($this->cachedTime, null, Util::toInt($nextCacheTime), true);
}
public function getRequiredSessionMode(): int
{
return static::NO_SESSION;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
if (!class_exists('\\sammo\\UniqueConst')) {
return '서버 초기화되지 않음';
}
if (!prepareDir('data/file_cache')) {
return 'cache 불가';
}
$storage = new \Nette\Caching\Storages\FileStorage('data/file_cache');
$cache = new Cache($storage);
$now = TimeUtil::nowDateTimeImmutable();
if ($modifiedSince) {
$diff = TimeUtil::DateIntervalToSeconds($modifiedSince->diff($now));
if (0 <= $diff && $diff < self::CACHE_SECONDS) {
$this->cachedTime = $modifiedSince;
return null;
}
}
$mapInfo = $cache->load("recent_map");
if ($mapInfo) {
$cachedTime = TimeUtil::secondsToDateTime($mapInfo['timestamp'], true, true);
$diff = $cachedTime->diff($now);
if (0 <= $diff && $diff < self::CACHE_SECONDS) {
$this->cachedTime = $cachedTime;
return $mapInfo['data'];
}
}
$history = getGlobalHistoryLogRecent(10);
$cachedMap = getWorldMap([
'year' => null,
'month' => null,
'aux' => null,
'neutralView' => true,
'showMe' => false,
]);
$cachedMap['history'] = $history;
$cachedMap['theme'] = GameConst::$mapName;
$timestamp = $now->getTimestamp();
$this->cachedTime = $now;
$map = [
'timestamp' => $timestamp,
'data' => $cachedMap,
];
$cache->save("recent_map", $map);
return $cachedMap;
}
}
+321
View File
@@ -0,0 +1,321 @@
<?php
namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use sammo\VersionGit;
use Nette\Caching\Cache;
use RuntimeException;
use sammo\APICacheResult;
use sammo\CityConst;
use sammo\GameConst;
use sammo\GameUnitConst;
use sammo\Json;
use sammo\TimeUtil;
use sammo\UniqueConst;
use function sammo\prepareDir;
class GetConst extends \sammo\BaseAPI
{
/** 반환하는 StaticValues 타입이 달라지면 +1 */
const CONST_API_VERSION = 2;
const CACHE_KEY = 'JSConst';
private ?string $cacheKey = null;
public function validateArgs(): ?string
{
return null;
}
public function getRequiredSessionMode(): int
{
return static::NO_SESSION;
}
public function findLastModified(): ?int
{
$rawResult = explode("\n", shell_exec('git status -u -s --no-rename'));
$files = [];
foreach ($rawResult as $rawLine) {
if (strlen($rawLine) < 3) {
continue;
}
$filePath = trim(substr($rawLine, 3));
if ($filePath[0] == '"') {
$filePath = substr($filePath, 1, strlen($filePath) - 2);
}
if (!file_exists($filePath)) {
continue;
}
$files[] = $filePath;
}
$lastModified = null;
foreach ($files as $filePath) {
$fileModified = filemtime($filePath);
if ($fileModified === false) {
continue;
}
if ($lastModified === null) {
$lastModified = $fileModified;
continue;
}
if ($lastModified > $fileModified) {
continue;
}
$lastModified = $fileModified;
}
if ($lastModified === null) {
return null;
}
return $lastModified;
}
public function getCacheKey(): string
{
if ($this->cacheKey !== null) {
return $this->cacheKey;
}
if (is_subclass_of('\\sammo\\VersionGit', '\\sammo\VersionGitDynamic')) {
$lastModified = $this->findLastModified();
if ($lastModified !== null) {
$versionHash = "lt{$lastModified}";
} else {
$versionHash = VersionGit::getHash();
}
} else {
$versionHash = VersionGit::getHash();
}
$apiVersion = static::CONST_API_VERSION;
$serverID = UniqueConst::$serverID;
$cacheKey = "{$apiVersion}_{$serverID}_{$versionHash}";
$this->cacheKey = $cacheKey;
return $cacheKey;
}
public function tryCache(): ?APICacheResult
{
if (is_subclass_of('\\sammo\\VersionGit', '\\sammo\VersionGitDynamic')) {
return new APICacheResult(TimeUtil::secondsToDateTime($this->findLastModified()??\time(), true, true));
}
return new APICacheResult(null, $this->getCacheKey(), 60, true);
}
public function readCache(Cache $cache): null|string|array|int|float|bool
{
$rawJSONCache = $cache->load(static::CACHE_KEY);
if ($rawJSONCache === null) {
return null;
}
$jsonCache = Json::decode($rawJSONCache);
if (!key_exists('cacheKey', $jsonCache)) {
return null;
}
$jsonCacheKey = $jsonCache['cacheKey'];
if ($jsonCacheKey !== $this->getCacheKey()) {
return null;
}
return $jsonCache['data'] ?? null;
}
public function extractObjClassInfo(string $objKey, callable $callerFunction): array
{
/** @var \sammo\iAction */
$target = $callerFunction($objKey);
if (!($target instanceof \sammo\iAction)) {
throw new \RuntimeException("{$objKey}의 대상이 iAction이 아님");
}
return [
'value' => $objKey,
'name' => $target->getName(),
'info' => $target->getInfo(),
];
}
public function extractObjClassInfoFromArray(array $constArray, callable $callerFunction): array
{
$result = [];
foreach ($constArray as $key => $target) {
if (is_string($target)) {
$actionInfo = $this->extractObjClassInfo($target, $callerFunction);
if (is_string($key)) {
$result[$key] = $actionInfo;
} else {
$result[$target] = $actionInfo;
}
continue;
}
if (is_array($target)) {
$result[$key] = $this->extractObjClassInfoFromArray($target, $callerFunction);
continue;
}
if(is_string($key) && is_int($target)){
//역전된 상황이다.
$result[$key] = $this->extractObjClassInfo($key, $callerFunction);
continue;
}
$result[$key] = $target;
}
return $result;
}
public function extractObjClassInfoFromGameConst(string $gameConstKey, callable $callerFunction): array
{
$gameConstKeyList = explode(".", $gameConstKey);
$target = (GameConst::${$gameConstKeyList[0]}) ?? [];
foreach(\array_slice($gameConstKeyList, 1) as $gameConstSubKey){
$target = $target[$gameConstSubKey] ?? [];
}
if (is_string($target)) {
return [$target => $this->extractObjClassInfo($target, $callerFunction)];
}
if (!is_array($target)) {
throw new \RuntimeException("GameConst::{$gameConstKey}의 값이 {$target}");
}
return $this->extractObjClassInfoFromArray($target, $callerFunction);
}
public function genConstData()
{
/** @var array<string,array{0:string,1:string[],2?:int> */
$gameConstKeys = [
'nationType' => [
'\sammo\buildNationTypeClass',
['availableNationType', 'neutralNationType']
],
'specialDomestic' => [
'\sammo\buildGeneralSpecialDomesticClass',
['defaultSpecialDomestic', 'availableSpecialDomestic', 'optionalSpecialDomestic']
],
'specialWar' => [
'\sammo\buildGeneralSpecialWarClass',
['defaultSpecialWar', 'availableSpecialWar', 'optionalSpecialWar']
],
'personality' => [
'\sammo\buildPersonalityClass',
['neutralPersonality', 'availablePersonality', 'optionalPersonality']
],
'item' => [
'\sammo\buildItemClass',
['allItems'],
1
],
];
//GameConst 중 BaseCommand는 시간 흐름, 장수에 따라 정보가 달라지므로 따로 처리해야함
$iActionInfo = [];
$iActionKeyMap = [];
foreach ($gameConstKeys as $mappedKey => $callerTarget) {
$flatLevel = 0;
if (is_array($callerTarget)) {
$callerFunction = $callerTarget[0];
$gameConstSubKey = $callerTarget[1];
if(count($callerTarget) > 2){
/** @var int */
$flatLevel = $callerTarget[2];
}
} else {
$gameConstSubKey = [$mappedKey];
$callerFunction = $callerTarget;
}
if (!is_callable($callerFunction)) {
throw new \RuntimeException("{$mappedKey} => {$callerFunction}이 callable이 아님");
}
$actionInfo = [];
foreach ($gameConstSubKey as $key) {
$appendInfo = $this->extractObjClassInfoFromGameConst($key, $callerFunction);
$actionInfo = array_merge($actionInfo, $appendInfo);
$iActionKeyMap[$key] = $mappedKey;
}
if($flatLevel > 0){
foreach(range(0, $flatLevel - 1) as $tryFlatLevel){
$actionInfo = array_merge(...array_values($actionInfo));
}
}
$iActionInfo[$mappedKey] = $actionInfo;
}
$crewtypeMap = [];
foreach(GameUnitConst::all() as $crewtypeObj){
$crewtypeMap[$crewtypeObj->id] = [
'value'=>(string)$crewtypeObj->id,
'name'=>$crewtypeObj->name,
'info'=>$crewtypeObj->getInfo(),
];
}
$iActionInfo['crewtype'] = $crewtypeMap;
return [
'gameConst' => get_class_vars('\sammo\GameConst'),
'gameUnitConst' => GameUnitConst::all(),
'cityConst' => CityConst::all(),
'cityConstMap' => [
'region' => CityConst::$regionMap,
'level' => CityConst::$levelMap,
],
'iActionInfo' => $iActionInfo,
'iActionKeyMap' => $iActionKeyMap,
];
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$cacheDir = $this->rootPath . '/data/file_cache';
if (!prepareDir($cacheDir)) {
throw new RuntimeException('cache 폴더 없음');
}
$storage = new \Nette\Caching\Storages\FileStorage($cacheDir);
$cache = new Cache($storage);
$currentCacheKey = $this->tryCache();
if($modifiedSince !== null && $currentCacheKey->lastModified == $modifiedSince){
return null;
}
if($reqEtag !== null && $currentCacheKey->etag == $reqEtag){
return null;
}
$constCache = $this->readCache($cache);
if ($constCache !== null) {
return [
'result' => true,
'cacheKey' => $this->getCacheKey(),
'data' => $constCache,
];
}
$constCache = $this->genConstData();
$cache->save(static::CACHE_KEY, Json::encode([
'cacheKey' => $this->getCacheKey(),
'data' => $constCache
]));
return [
'result' => true,
'cacheKey' => $this->getCacheKey(),
'data' => $constCache,
];
}
}
@@ -0,0 +1,31 @@
<?php
namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use function sammo\getCurrentHistory;
class GetCurrentHistory extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$history = getCurrentHistory();
return [
'result' => true,
'data' => $history,
];
}
}
+105
View File
@@ -0,0 +1,105 @@
<?php
namespace sammo\API\Global;
use sammo\DB;
use sammo\Json;
use sammo\KVStorage;
use sammo\Session;
use function sammo\getAllNationStaticInfo;
use function sammo\increaseRefresh;
class GetDiplomacy extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$userID = $session->userID;
increaseRefresh("중원정보", 1);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$myNationID = $db->queryFirstField('SELECT nation FROM general WHERE owner=%i', $userID);
$nations = array_filter(getAllNationStaticInfo(), function (array $nation) {
return $nation['level'];
});
uasort($nations, function (array $lhs, array $rhs) {
return - ($lhs['power'] <=> $rhs['power']);
});
foreach(array_keys($nations) as $nationID){
$nations[$nationID]['cities'] = [];
}
$realConflict = [];
foreach ($db->queryAllLists('SELECT nation, city, name, conflict FROM city') as [
$nationID,
$cityID,
$cityName,
$rawConflict
]) {
if($nationID != 0){
$nations[$nationID]['cities'][] = $cityName;
}
if($rawConflict == '{}'){
continue;
}
$rawConflict = Json::decode($rawConflict);
if (count($rawConflict) < 2) {
continue;
}
$sum = array_sum($rawConflict);
$conflict = [];
foreach ($rawConflict as $nationID => $killnum) {
$conflict[$nationID] = round(100 * $killnum / $sum, 1);
}
$realConflict[] = [$cityID, $conflict];
};
$neutralDiplomacyMap = [
3 => 2,
4 => 2,
5 => 2,
6 => 2,
7 => 2,
];
$diplomacyList = [];
foreach ($db->queryAllLists('SELECT me, you, state FROM diplomacy') as [$me, $you, $state]) {
if (!key_exists($me, $diplomacyList)) {
$diplomacyList[$me] = [];
}
if ($me != $myNationID && $you != $myNationID) {
$diplomacyList[$me][$you] = $neutralDiplomacyMap[$state] ?? $state;
} else {
$diplomacyList[$me][$you] = $state;
}
}
return [
'result' => true,
'nations' => array_values($nations),
'conflict' => $realConflict,
'diplomacyList' => $diplomacyList,
'myNationID' => $myNationID,
];
}
}
+188
View File
@@ -0,0 +1,188 @@
<?php
namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use sammo\APICacheResult;
use sammo\DB;
use sammo\Json;
use sammo\UniqueConst;
use sammo\Util;
use sammo\Validator;
use function sammo\checkLimit;
use function sammo\increaseRefresh;
use function sammo\templateLimitMsg;
class GetHistory extends \sammo\BaseAPI
{
public string|null $cacheHash = null;
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('required', ['year', 'month'])
->rule('lengthMin', 'serverID', 1)
->rule('integer', 'year')
->rule('integer', 'month');
if (!$v->validate()) {
return $v->errorStr();
}
if (!$this->args['serverID']) {
$this->args['serverID'] = UniqueConst::$serverID;
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_LOGIN | static::REQ_READ_ONLY;
}
public function tryCache(): ?APICacheResult
{
if (!$this->cacheHash) {
return null;
}
return new APICacheResult(
null,
$this->getCacheKey($this->args['serverID'], $this->args['year'], $this->args['month'], $this->cacheHash)
);
}
private function getHistory(string $serverID, int $year, int $month): array
{
$db = DB::db();
$history = $db->queryFirstRow(
'SELECT * FROM ng_history WHERE server_id = %s AND year = %i AND month = %i',
$serverID,
$year,
$month
);
$hash = hash(
'sha256',
"[" . join(',', [
$history['global_history'],
$history['global_action'],
$history['nations'],
$history['map'],
]) . "]"
);
$history['global_history'] = Json::decode($history['global_history']);
$history['global_action'] = Json::decode($history['global_action']);
$history['nations'] = Json::decode($history['nations']);
$history['map'] = Json::decode($history['map']);
$history['hash'] = $hash;
return $history;
}
public function parseEtag(?string $etag): ?array
{
if (!$etag) {
return null;
}
$tags = explode('-', $etag);
if (count($tags) != 4) {
return null;
}
if (!is_numeric($tags[1])) {
return null;
}
if (!is_numeric($tags[2])) {
return null;
}
return [$tags[0], Util::toInt($tags[1]), Util::toInt($tags[2]), $tags[3]];
}
public function getCacheKey(string $serverID, int $year, int $month, string $cacheHash): string
{
return "{$serverID}-{$year}-{$month}-{$cacheHash}";
}
public function checkCached(?string $reqEtag): ?string
{
if (!$reqEtag) {
return null;
}
$parsedTags = $this->parseEtag($reqEtag);
if (!$parsedTags) {
return null;
}
$serverID = $this->args['serverID'];
$year = Util::toInt($this->args['year']);
$month = Util::toInt($this->args['month']);
[$cachedServerID, $cachedYear, $cachedMonth, $cachedHash] = $parsedTags;
if ($cachedServerID !== $serverID || $cachedYear !== $year || $cachedMonth !== $month) {
return null;
}
//tag로 hash를 굳이 붙이고 왔다면, 이미 데이터를 가지고 있다고 가정한다.
return $cachedHash;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$checkCache = $this->checkCached($reqEtag);
if ($checkCache) {
$this->cacheHash = $checkCache;
return null;
}
$serverID = $this->args['serverID'];
$year = $this->args['year'];
$month = $this->args['month'];
$db = DB::db();
if ($serverID === UniqueConst::$serverID) {
if (!$session->isGameLoggedIn()) {
return '진행중인 서버의 연감은 게임에 로그인해야 볼 수 있습니다.';
}
increaseRefresh("연감", 1);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner = %i', $session->userID);
if (!$me) {
return '장수가 사망했습니다.';
}
$con = checkLimit($me['con']);
if ($con >= 2) {
return templateLimitMsg($me['turntime']);
}
}
[$f_year, $f_month] = $db->queryFirstList(
'SELECT year, month FROM ng_history WHERE server_id = %s ORDER BY year ASC, month ASC LIMIT 1',
$serverID
);
if ($f_year === null || $f_month === null) {
return '올바르지 않은 서버 아이디입니다.';
}
$firstYearMonth = Util::joinYearMonth($f_year, $f_month);
[$l_year, $l_month] = $db->queryFirstList(
'SELECT year, month FROM ng_history WHERE server_id = %s ORDER BY year DESC, month DESC LIMIT 1',
$serverID
);
$lastYearMonth = Util::joinYearMonth($l_year, $l_month);
$queryYearMonth = Util::joinYearMonth($year, $month);
if ($queryYearMonth < $firstYearMonth || $queryYearMonth > $lastYearMonth) {
return '올바르지 않은 범위입니다.';
}
$history = $this->getHistory($serverID, $year, $month);
$this->cacheHash = $history['hash'];
return [
'result' => true,
'data' => $history,
];
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use sammo\MapRequest;
use sammo\Validator;
use function sammo\getWorldMap;
class GetMap extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('in', 'neutralView', [0, 1])
->rule('in', 'showMe', [0, 1]);
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)
{
return getWorldMap(new MapRequest([
'neutralView' => !!($this->args['neutralView'] ?? false),
'showMe' => !!($this->args['showMe'] ?? false),
]));
}
}
+65
View File
@@ -0,0 +1,65 @@
<?php
namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use function sammo\getAllNationStaticInfo;
use function sammo\getNationStaticInfo;
class GetNationList extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$db = DB::db();
$nations = getAllNationStaticInfo();
uasort($nations, function ($lhs, $rhs) {
return $rhs['power'] <=> $lhs['power'];
});
$nations[0] = getNationStaticInfo(0);
foreach ($db->query('SELECT npc,name,nation,officer_level,permission FROM `general` ORDER BY dedication DESC') as $general) {
$nationID = $general['nation'];
$permission = $general['permission'];
if($permission != 'auditor' && $permission != 'ambassador'){
unset($general['permission']);
}
if($general['officer_level'] < 5){
$general['officer_level'] = 1;
}
if (!key_exists('generals', $nations[$nationID])) {
$nations[$nationID]['generals'] = [];
}
$nations[$nationID]['generals'][] = $general;
}
foreach ($db->queryAllLists('SELECT city, name, nation FROM city') as [$cityID, $cityName, $nationID]) {
if (!key_exists('cities', $nations[$nationID])) {
$nations[$nationID]['cities'] = [];
}
$nations[$nationID]['cities'][$cityID] = $cityName;
}
return [
'result' => true,
'nations' => $nations,
];
}
}
@@ -5,6 +5,7 @@ namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\General;
use sammo\KVStorage;
@@ -80,6 +81,7 @@ class BuyHiddenBuff extends \sammo\BaseAPI
$inheritBuffList[$type] = $level;
$general->setAuxVar('inheritBuff', $inheritBuffList);
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
$general->increaseRankVar(RankColumn::inherit_point_spent_dynamic, $reqAmount);
$general->applyDB($db);
return null;
}
@@ -5,6 +5,7 @@ namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\General;
use sammo\KVStorage;
@@ -52,6 +53,7 @@ class BuyRandomUnique extends \sammo\BaseAPI
$general->setAuxVar('inheritRandomUnique', TimeUtil::now());
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
$general->increaseRankVar(RankColumn::inherit_point_spent_dynamic, $reqAmount);
$general->applyDB($db);
return null;
}

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