Compare commits

...
122 Commits
Author SHA1 Message Date
Hide_D 1ca07286a4 Revert "game: 국가 임관 시, 기존 등용장 무효화"
This reverts commit 376aed9787.
2023-07-12 20:19:59 +10:00
Hide_D 376aed9787 game: 국가 임관 시, 기존 등용장 무효화 2023-07-11 22:47:24 +10:00
Hide_D 246751b4dd feat: 등용장 일괄 무효화 추가 2023-07-11 22:43:09 +10:00
Hide_D 7f3a9d69ca misc: FIXME 2023-07-11 22:11:01 +10:00
Hide_D a4106f6242 game: 등용장 수락은 재야 상태에서만 가능 2023-07-11 22:02:07 +10:00
Hide_DandGitea f233e8241e Merge pull request 'feat,refac: General 테이블의 벌점(갱신) 항목을 별도 테이블로 분리' (#232) from general_access_log into devel 2023-07-08 09:10:53 +00:00
Hide_D 79dedea47c fix: 물자원조 조사 2023-07-08 02:04:17 +00:00
Hide_D e106a6a3cf fix: queryMode 조회 문제
- 아니 PHP야 enum에 ->value 좀..
2023-07-07 18:44:36 +00:00
Hide_D ee3d84d7b0 refac: General 객체 생성을 GeneralQueryMode를 활용
- 기존 $constructMode
- 버그 있음..?
2023-07-07 18:39:23 +00:00
Hide_D b4f197b7d8 feat: GeneralQueryMode Enum 추가
- mergeQueryColumn, createGeneralObjListFromDB, createGeneralObjFromDB 호출시
 column 특수 모드 지정
2023-07-07 18:14:55 +00:00
Hide_D e3c89a37aa fix: 구 내정보 페이지 변수 조회 문제 2023-07-07 17:29:03 +00:00
Hide_D ad0770d1be fix: 접속량 정보 변수명 2023-07-07 17:20:24 +00:00
Hide_D 161ed97a34 fix: GeneralAccessLogColumn 인자 값 문제
- PHP 제발 반성 좀... 왜 ->value가 필요해..?
2023-07-07 17:12:15 +00:00
Hide_D f66008da56 refac, fix: General 객체 생성 과정에서 accessLog 분리
- 생성자 인수 1개 추가,
- mergeQueryColumn에서 $accessLogColumn에 정상적으로 enum[] 반영
- createGeneralObjListFromDB를 쿼리 1회 분리
- General에 getAccessLogVar() 추가
  - 변경 기능 제공 예정 '없음'
- 변경된 생성자에 맞게 호출 부 변경
- NPC인 경우 accessLog 조회값이 null일 수 있으므로 반영
2023-07-07 17:08:05 +00:00
Hide_D 6b400f76cf fix: 오타 수정 2023-07-07 15:58:18 +00:00
Hide_D 758ae06fd9 refac, wip: con 삭제,생성 관련 2023-07-07 10:57:52 +00:00
Hide_D 49429e1e7e refac, wip: con -> refreshScore 2023-07-07 10:57:52 +00:00
Hide_D c9dd873019 refac, wip: 벌점(connect, con) 변경
- 벌점: refreshScoreTotal
- 순간벌점: refreshScore
2023-07-07 10:57:52 +00:00
Hide_D 3ae49456b1 fix: general_access_log에 벌점 관련 데이터 누락 2023-07-07 10:57:52 +00:00
Hide_D 9bf7bd0fda refac,wip: refresh 수치를 이전 중
- connect, con을 잊었음!
2023-07-07 10:57:51 +00:00
Hide_D a9b51977d4 refac: lastrefresh를 general_access_log로 이전
- last_refresh에 index를 걸 것인지는 고려 필요
  - 안 거는게 차라리 나을 수도 있음
- 불필요해보이는 값 확인: nation_id,
2023-07-07 10:57:51 +00:00
Hide_D 50408ed516 feat: TableName Enum 2023-07-07 10:57:51 +00:00
Hide_D b0cdf3ccb5 refac: General::lastconnect 삭제
- 안쓰는데..?
- api_log로 어느새 이전된건가?
2023-07-07 10:57:51 +00:00
Hide_D ea80b85b33 refac: 갱신 시 refresh를 general_access_log로 이동 2023-07-07 10:57:51 +00:00
Hide_D 39ca3e2bb9 feat: GeneralAccessLog 구조 변경
- 기본값 최대한 많이 사용
2023-07-07 10:57:51 +00:00
Hide_D f8cc0c9c92 feat: GeneralAccessLog table 준비
- general 테이블에서 유저 접속과 관련한 로그만 분리
- ip 정보는 api 접속부에서 기록하므로 제외
2023-07-07 10:57:51 +00:00
Hide_D 7a9ef6454c fix: 정체불명의 ts type error fix
- 이 변경이 없어도 잘 되어야함. type에 undefined로 놓는게 어딨어?
2023-07-07 10:57:50 +00:00
Hide_D d48c27dccb misc: 관리자5번 도구에서 벌점 정보 제거 2023-07-07 10:57:50 +00:00
Hide_D 5a565c2678 feat: formatListOfBackticks에서 인자로 BackedEnum 사용 가능 2023-07-07 10:57:50 +00:00
Hide_D 1e0875ae73 game: 국력 계산식에 '벌점' 제거 2023-07-07 10:57:50 +00:00
Hide_D 33759d24e5 refac: 접속 로그를 날짜_refresh.txt에서 api_log로 통일
- path가 refresh로 고정
2023-07-07 10:57:50 +00:00
Hide_D 033e75de5c refac: 구 멀티 검사 페이지 삭제
- IP로만 구분하던 방식
- IP를 general에서 없애므로 삭제
2023-07-07 10:57:45 +00:00
Hide_D f2f8374fd4 fix: 쉼표를 주의하시오 2023-07-04 10:24:32 +09:00
Hide_D e891525d56 refac: general_turn, nation_turn 불필요한 인덱스 제거 2023-07-03 17:04:38 +00:00
Hide_D 93bc8304ce misc: 몇 가지 눈에 보이는 오타 수정 (#231)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/231
2023-07-03 22:32:42 +09:00
Jinhyun Kim d4218f409c 몇 가지 눈에 보이는 오타 수정 2023-07-03 20:59:05 +09:00
Hide_D 462de95866 misc: php xdebug profiler ignore 2023-07-02 17:42:56 +00:00
Hide_D dad477ed14 misc: 불필요산 #app css 제거
- 필요하다면 vue page에서 직접 요구하여야 함.
2023-07-02 17:06:01 +00:00
Hide_D 660258f715 refac: 메인 페이지 바 표시 형식 변경
- 상 하단 분리 대신 하단의 position:fixed bar로 변경
- iPhone에서 좌우 스크롤이 유도되는 것은 완전 해결되지 않음
- 모든 컨텐츠가 viewport 밖을 넘어서지 않도록 않도록 해야 할 것으로
- 예: 500px viewport, 498px content
2023-07-02 17:05:14 +00:00
Hide_D 9f6c7d9489 fix: 누락된 php breakpoint 수정 2023-06-30 16:34:14 +00:00
Hide_D de17d87f47 fix: 비일관적인 breakpoint 정정
- md가 아니라 lg를 기준으로 잡아야 함
- lg의 기준 breakpoint를 940으로 변경
- is100pxMode의 기준 역시 lg breakpoint와 일치
2023-06-30 16:30:44 +00:00
Hide_D f8ebcf91b1 fix: 삼성 브라우저 draggable workaround 2023-06-28 14:50:52 +00:00
Hide_D d25d414057 dep: vuedraggable-es 2023-06-28 14:50:37 +00:00
Hide_D 96a9254bf8 misc: tabSize 4 2023-06-28 13:45:24 +00:00
Hide_D 96643567d4 game: 애니집결 시나리오의 대사 빈도를 낮춤 2023-06-24 16:53:21 +00:00
Hide_D 0a6db3d21f fix: 이민족 발동시 서버 시간 변경 문제 2023-06-23 11:27:59 +00:00
Hide_D 8a4cbbb976 game: 애니집결 10차 시나리오 2023-06-23 19:28:28 +09:00
Hide_D 696ba0b341 fix(game): 병가의 세율에 따른 인구 증감이 '정수'로 고정되는 문제
- onCalcNationalIncome에서 pop은 0~0.125 사이임
2023-06-18 13:23:01 +09:00
Hide_D 4efcbaed6a misc: d_setting에 관련 코드가 추가되어 TODO 제거 2023-06-11 21:57:45 +09:00
Hide_D eda5ecb124 feat: d_setting에 ServerEnv 추가 2023-06-11 21:56:26 +09:00
Hide_D 0ef69178a5 feat: 이민족 발동 시 장수수에 따라 턴시간 조절 2023-06-11 21:44:22 +09:00
Hide_D 5596eca326 feat: 서버 제어용 변수 공간 추가 2023-06-11 21:40:07 +09:00
Hide_D af2dec7e2c refac: 턴시간 변경에 락 무시하는 기능 추가 2023-06-11 21:27:14 +09:00
Hide_D 435dae801f refac: _admin1 턴시간 변경을 changeServerTerm으로 이전 2023-06-11 21:25:53 +09:00
Hide_D 320c8191dc feat: ServerTool::changeServerTerm
- 서버 턴 시간을 바꾸는 명령
- 기존 _admin1.php
2023-06-11 21:24:53 +09:00
Hide_D 803e18e3c3 fix: 이민족 이벤트 종료시 메시지 2023-06-11 21:02:57 +09:00
Hide_D fbac218c34 fix: 이민족 발동 시, 초기 이성이 없으면 동작하지 않도록 2023-06-10 22:41:19 +09:00
Hide_D 2e6ea3a00d fix: isunited warning 수정 2023-06-08 23:31:46 +09:00
Hide_D 1f8812c939 fix: MAX_RNG_SUPPORT_BIT warning 2023-06-08 23:23:05 +09:00
Hide_D 44c2323883 fix: 임시 땜빵 베팅 2023-06-07 00:23:36 +09:00
Hide_D 82fb532e4b fix: 조사 (으)로 미 반영부분 수정 2023-06-06 16:51:42 +09:00
Hide_D ae6ca5c1ec fix: 성벽 선제 시 분쟁 대상이 도시로 나타나지 않는 버그 수정 2023-06-06 16:41:13 +09:00
Hide_D 30ac7da4d7 misc: 이민족 생성 시, 전쟁 금지 및 임관 금지 해제 2023-06-04 20:22:45 +09:00
Hide_D 8c30634fd1 fix: 리셋 시 최근 읽은 메시지 번호를 초기화해야 함 2023-06-03 10:58:15 +09:00
Hide_D 59761743dc misc: 이민족 소환 권한을 2명에게 부여 2023-05-22 21:56:15 +09:00
Hide_D 5952dba533 fix: 천통시 이민족 소환에 npc 여부를 제대로 계산하지 않는 문제 2023-05-22 21:52:35 +09:00
Hide_D 2518ac021d fix: ProvideNPCTroopLeader 경고 우회 2023-05-22 02:48:41 +09:00
Hide_D e656c1e567 fix: 천통시 이민족 권한을 유저에게 부여
- 군주가 NPC인 경우 참모
- 참모도 NPC라면 각 수뇌까지
2023-05-22 02:43:54 +09:00
Hide_D b89c045f85 feat: 천하통일 시 군주에세 이민족이 침입 이벤트 권한 부여
- 세가지 종류 난이도
  - 천통국가 기준 [장수 수, 종합 스탯, 기술 수치, 숙련 수치]
  - 어려움:  2배, 1.2배, 최고등급, 1배
  - 보통: 2배, 1.2배, 동일 기술, 0.5배
  - 쉬움: 1배, 1배, 20% 낮은 기술, 숙련 없음
- 이민족 멸망시 타 이민족으로 임관
2023-05-22 02:41:17 +09:00
Hide_D d347054ad0 feat: 이민족 침입 메시지 타입 추가 2023-05-22 02:38:35 +09:00
Hide_D 3ebc44ea5a fix: RaiseInvader의 중첩 호줄 대비
- isunited 변수를 빠르게 1로 설정
- 만약 RaiseInavder를 빠르게 두번 호출하더라도 isunited 변수를 검사하게 하여 대응 가능
2023-05-22 02:19:47 +09:00
Hide_D 57c8c3f6a4 feat: MessageType 간이 생성 함수 추가
- General 객체에서 생성
- 왜 여태까지 이 함수가 없었을까?
2023-05-22 02:15:45 +09:00
Hide_D fee769714d feat: System MessageTarget를 빠르게 생성하는 함수 2023-05-22 01:55:09 +09:00
Hide_D 9fcb24533a feat: sendPrivateMsgAsNotice 인자로 MessageTarget 추가 2023-05-22 01:44:25 +09:00
Hide_D 1061632290 feat: 단순한 공지용 개인 메시지 전송 기능 2023-05-22 01:41:35 +09:00
Hide_D 7dc297a266 fix: 성벽 선제 후 전투 종료시 점유율 관련 문제 2023-05-20 13:04:37 +09:00
Hide_D f019a642a2 fix: 구형 관리자 도구 warning 수정 2023-05-20 12:56:57 +09:00
Hide_D 5554ac3003 fix: 성벽 전투 반영 2023-05-20 03:37:09 +09:00
Hide_D 7f9ad8b7d5 fix: 정란/벽력의 성벽선제가 정상적으로 반영되지 않는 문제
- 수비/성벽
- 점유율
2023-05-20 01:03:19 +09:00
Hide_D 82af3a2e2d fix: 수비자에 수비 도시 정보가 입력되지 않는 버그 수정 2023-05-19 19:16:39 +09:00
Hide_D 7a4fcb30dc fix: 거울세계에서 국가 규모 승급이 일어나지 않던 버그 수정 2023-05-12 01:21:12 +09:00
Hide_D 256326f5d4 game: 정란, 벽력거 설명 추가 2023-05-12 00:07:01 +09:00
Hide_D 505f615203 game: 성벽선제인 경우에만 성벽도 선제공격 2023-05-12 00:07:01 +09:00
Hide_D 4e504e9679 game: 성벽이 선제공격 2023-05-12 00:07:01 +09:00
Hide_D 18f9d87a29 fix: 성벽 선제가 호출조차 되지 않는 버그 수정 2023-05-12 00:07:01 +09:00
Hide_D 2ad0c6e509 fix: 도시 관련 전투 제어 2023-05-12 00:07:00 +09:00
Hide_D 74b9e0b4a5 feat: CrewType에 iAction 개념을 넣고 처리할 수 있도록
- GameUnitDetail에 iAction 리스트 추가

fix: 누락분 수정

fix: crewtype 미지정시 기본 병종
2023-05-12 00:05:25 +09:00
Hide_D 486ac65767 wip: process_war에서 defenderList 변경
- defenderList를 General[] 에서 WarUnit[]으로 변경
- extractBattleOrder를 WarUnit을 받도록 변경
2023-05-10 02:31:43 +09:00
Hide_D 483641bcd5 feat: extractBattleOrder 함수가 공격자를 받아서 처리할 수 있도록 변경 2023-05-10 01:28:00 +09:00
Hide_D ffdacc2cfb game: 차병종 상성 변경
- 정란: 현행 유지
- 충차: 현행 유지
- 벽력거: 받는 피해 44% 증가
  - 정란의 상성과 동일하게 변경
- 목우: 주는 피해 20% 감소
2023-05-10 00:59:56 +09:00
Hide_D 4eac86da58 game: 저지시 쌀을 소모하도록 변경
- 오르는 숙련 대비 0.25배
- 즉, 일반 공격력 대비 0.9 * 0.25만큼
2023-05-10 00:39:10 +09:00
Hide_D 77fc38c899 misc: 세력장수에서 숫자 셀에는 숫자 대소비교 필터 설정 2023-04-30 19:37:52 +09:00
Hide_D 0bf49ebfb9 game: 능력치가 상한에 도달하면 더이상 오르지 않음 2023-04-30 00:29:15 +09:00
Hide_D 93f0516121 Revert "game: 스탯 제한을 순수 스탯 대상으로만 변경"
This reverts commit 71a3ffa21c.
2023-04-30 00:22:14 +09:00
Hide_D 36406c8001 game: 물자조달도 전방 내정 감소가 적용 2023-04-30 00:15:41 +09:00
Hide_D 836adcfe3c game: 전방 내정시, 수도가 전방이어도 감쇠되도록 설정
- 185년까지는 해당 없음(디버프 * 0%)
- 이후 1년마다 실제 적용량 대비 5%씩 가산 적용됨
- 205년이 되면 수도여도 전방 내정 감쇠가 그대로 적용됨
2023-04-30 00:15:17 +09:00
Hide_D 71a3ffa21c game: 스탯 제한을 순수 스탯 대상으로만 변경 2023-04-29 23:47:47 +09:00
Hide_D 38f10b5f09 game: 최대 레벨, 능력치 제한을 255로 변경 2023-04-29 23:46:22 +09:00
Hide_D da6b1fe7f1 game: 내부 스탯 제한을 2중으로 2023-04-29 23:40:30 +09:00
Hide_D 034e6374cc game: 최대 환산 능력치를 300으로 제한 2023-04-29 23:30:11 +09:00
Hide_D 9b95163f24 fix: 명성 최대 레벨 지정이 없었음 2023-04-29 23:18:55 +09:00
Hide_D 91b7934ee3 fix: KakaoUtil의 저장 키 문제 2023-04-25 23:09:01 +09:00
Hide_D 41216893a1 fix: 감찰부 대상 API 순서에 따라 잘못 표기 되는 문제
- API 결과값과 현재 대상 비교하는 코드 추가
2023-04-23 16:53:17 +09:00
Hide_D 3553b87748 fix: 지도 제목에 툴팁 표기 고장 수정
- 동작하지 않는 vMyTooltip 제거
2023-03-30 02:39:57 +09:00
Hide_D 3e5e584fce fix: 오타 수정
- 영향받는 코드는 없었을 것으로.
2023-03-30 01:19:52 +09:00
Hide_D afb53d121b fix: 특기 초기화시 가득차면 사용 풀이 리셋되지 않는 버그 수정 2023-03-28 10:05:48 +09:00
Hide_D 1780122936 fix: 모든 내특/전특 사용시 에러나는 문제 수정 2023-03-28 09:54:24 +09:00
sars 64aa5d041f Revert "긴급 버그 패치, 내특 줄 수 있는게 하나도 없으면 강제로 상재로 주고 턴 넘기는것으로 긴급패치, 히데님이 알아서 제대로 고칠것, (2로 해두면 상재가 아니라 아에 버그가 떠서 그냥 롤백시키고 히데님이 다 고치는걸로 방치하기로 결정)"
This reverts commit fbccfbb65e.
2023-03-27 09:54:37 -07:00
sars fbccfbb65e 긴급 버그 패치, 내특 줄 수 있는게 하나도 없으면 강제로 상재로 주고 턴 넘기는것으로 긴급패치, 히데님이 알아서 제대로 고칠것 2023-03-27 09:49:00 -07:00
Hide_D 13eb0d4eae fix: 토너먼트 표기 문구 수정 2023-03-26 15:56:04 +09:00
Hide_D 3969c47f07 Revert "fix: 임시로 대문에서 로그인 체크를 직접 하도록 변경"
This reverts commit c7e0d6d2cb.
2023-03-26 15:55:38 +09:00
Hide_D c7e0d6d2cb fix: 임시로 대문에서 로그인 체크를 직접 하도록 변경 2023-03-26 15:52:06 +09:00
Hide_D 9e997a7ee2 feat: 도시 장수 정의에 nationID를 추가 2023-03-26 00:58:53 +09:00
Hide_D 9a8f70d87b fix: 감찰부 안보이는 버그 수정
- query로 옮겨서 생기는 문제
2023-03-26 00:58:32 +09:00
Hide_D 7132aeab0c fix: installVue3Components() 호출부 통일 2023-03-26 00:48:05 +09:00
Hide_D 994c73adb2 feat: 설문조사 정보도 DB정보를 이용하여 한번만 처리 2023-03-25 03:07:38 +09:00
Hide_D 9206b74500 feat: 이미 읽은 메시지를 DB에서 처리 2023-03-25 02:09:23 +09:00
Hide_D 5294aefbbd misc: 동향 변경 안내 시간 단축 2023-03-24 03:03:50 +09:00
Hide_D 8f0f586af9 fix: 버그 수정 2023-03-24 02:44:14 +09:00
Hide_D 9121533b93 fix: 국가 승급을 Event로 떼내어야 함
- 부대장 지급보다 앞으로
2023-03-24 02:43:07 +09:00
Hide_D 90bff7b210 misc: 연도 업데이트 2023-03-22 23:22:46 +09:00
Hide_D 55f7b87ced misc: GetConst의 cache key를 getVersion으로 2023-03-22 23:19:28 +09:00
213 changed files with 3413 additions and 2434 deletions
+2
View File
@@ -69,3 +69,5 @@ gateway/js/*
gateway/css/* gateway/css/*
*.db-journal *.db-journal
d_log/cachegrind.*
+1 -1
View File
@@ -29,5 +29,5 @@
"josa", "josa",
"sammo" "sammo"
], ],
"editor.tabSize": 2 "editor.tabSize": 4
} }
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License The MIT License
Copyright (c) 2022 Hide_D, 62che Copyright (c) 2023 Hide_D, 62che
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+3 -3
View File
@@ -30,10 +30,10 @@ require(__DIR__ . '/../vendor/autoload.php');
<body> <body>
<div class="container"> <div class="container">
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 설치</h1> <h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 설치</h1>
<div class="row justify-content-md-center"> <div class="row justify-content-lg-center">
<div class="col col-12 col-md-10 col-lg-7"> <div class="col col-12 col-lg-10 col-lg-7">
<div class="card" id="db_form_card" style="display:none"> <div class="card" id="db_form_card" style="display:none">
<h3 class="card-header"> <h3 class="card-header">
설치(DB 설정) 설치(DB 설정)
+1 -22
View File
@@ -74,28 +74,7 @@ switch ($btn) {
case "120분턴": $turnterm = 120; break; case "120분턴": $turnterm = 120; break;
default: throw new \Exception("알 수 없는 턴 기간"); default: throw new \Exception("알 수 없는 턴 기간");
} }
$oldunit = $admin['turnterm'] * 60; ServerTool::changeServerTerm($turnterm);
$unit = $turnterm * 60;
$unitDiff = $unit / $oldunit;
$servTurnTime = new \DateTimeImmutable($admin['turntime']);
foreach ($db->query('SELECT no,turntime FROM general') as $gen) {
$genTurnTime = new \DateTimeImmutable($gen['turntime']);
$timeDiff = TimeUtil::DateIntervalToSeconds($genTurnTime->diff($servTurnTime));
$timeDiff *= $unitDiff;
$newGenTurnTime = $servTurnTime->add(TimeUtil::secondsToDateInterval($timeDiff));
$db->update('general', [
'turntime'=>$newGenTurnTime->format('Y-m-d H:i:s.u')
], 'no=%i', $gen['no']);
}
$turn = ($admin['year'] - $admin['startyear']) * 12 + $admin['month'] - 1;
$starttime = $servTurnTime->sub(TimeUtil::secondsToDateInterval($turn * $unit))->format('Y-m-d H:i:s');
$starttime = cutTurn($starttime, $turnterm, false);
$gameStor->turnterm = $turnterm;
$gameStor->starttime = $starttime;
pushGlobalHistoryLog(["<R>★</>턴시간이 <C>$btn</>으로 변경됩니다."]);
break; break;
} }
+10 -10
View File
@@ -38,13 +38,13 @@ if ($genlist) {
} }
switch ($btn) { switch ($btn) {
case "전체 접속허용": case "전체 접속허용":
$db->update('general', [ $db->update('general_access_log', [
'con' => 0 'refresh_score' => 0
], true); ], true);
break; break;
case "전체 접속제한": case "전체 접속제한":
$db->update('general', [ $db->update('general_access_log', [
'con' => 1000 'refresh_score' => 1000
], true); ], true);
break; break;
case "블럭 해제": case "블럭 해제":
@@ -186,14 +186,14 @@ switch ($btn) {
], '`no` IN %li', $genlist); ], '`no` IN %li', $genlist);
break; break;
case "접속 허용": case "접속 허용":
$db->update('general', [ $db->update('general_access_log', [
'con' => 0 'refresh_score' => 0
], '`no` IN %li', $genlist); ], '`general_id` IN %li', $genlist);
break; break;
case "접속 제한": case "접속 제한":
$db->update('general', [ $db->update('general_access_log', [
'con' => 1000 'refresh_score' => 1000
], '`no` IN %li', $genlist); ], '`general_id` IN %li', $genlist);
break; break;
case "메세지 전달": case "메세지 전달":
$text = $msg ?? ''; $text = $msg ?? '';
-133
View File
@@ -1,133 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 5) {
die(requireAdminPermissionHTML());
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$conlimit = $gameStor->conlimit;
$ipGroupList = Util::arrayGroupBy(
$db->query(
'SELECT name,ip,lastconnect,owner,block,substring_index(ip,".",3) as ip_c from general WHERE ip!="" and npc<2'
),
'ip_c'
);
function colorBlockedName($general)
{
if (!$general['blocked']) {
return $general['name'];
}
return "<span style='color:magenta;'>{$general['name']}</span>";
}
?>
<!DOCTYPE html>
<html>
<head>
<title>멀티관리</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('ts', 'common', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td>멀 티 관 리<br><?= backButton() ?></td>
</tr>
</table>
<form name=form1 method=post action=_admin4_submit.php>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=80 align=center rowspan=3>회원선택<br><br>
<font color=cyan>NPC</font><br>
<font color=skyblue>NPC유저</font><br>
<font color=red>접속제한</font><br><b style=background-color:red;>블럭회원</b>
</td>
<td width=105 rowspan=3>
<?php
echo "
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:14px'>";
foreach ($db->query('SELECT no,name,npc,block,con from general where ip!=\'\' order by npc,ip') as $general) {
$style = "style=;";
if ($general['block'] > 0) {
$style .= "background-color:red;";
}
$npcColor = getNPCColor($general['npc']);
if($npcColor !== null){
$style .= "color:{$npcColor};";
}
echo "
<option value={$general['no']} $style>{$general['name']}</option>";
}
echo "
</select>";
?>
</td>
<td width=100 align=center>블럭</td>
<td width=504>
<input type=submit name=btn value='블럭 해제'><input type=submit name=btn value='1단계 블럭'><input type=submit name=btn value='2단계 블럭'><input type=submit name=btn value='3단계 블럭'><input type=submit name=btn value='무한삭턴'><br>
1단계:발언권, 2단계:턴블럭
</td>
</tr>
<tr>
<td align=center>강제 사망</td>
<td><input type=submit name=btn value='강제 사망'></td>
</tr>
<tr>
<td align=center>메세지 전달</td>
<td><input type=textarea size=60 maxlength=255 name=msg style=background-color:black;color:white;><input type=submit name=btn value='메세지 전달'></td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td align=center width=100>장수명</td>
<td align=center width=180>최근로그인</td>
<td align=center width=129>IP</td>
<td align=center width=100>ID</td>
</tr>
<?php foreach ($ipGroupList as $ipGroupC => $users) : ?>
<tr>
<td><?= join('<br>', array_map('\sammo\colorBlockedName', $users)) ?></td>
<td><?= join('<br>', array_column($users, 'lastconnect')) ?></td>
<td><?= join('<br>', array_column($users, 'ip')) ?></td>
<td><?= join('<br>', array_column($users, 'owner')) ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php
//NOTE: password의 md5 해시가 같은지 확인하는 방식으로는 앞으로 잡아낼 수 없다. 폐기
?>
</form>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td><?= backButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
</body>
</html>
-86
View File
@@ -1,86 +0,0 @@
<?php
namespace sammo;
use sammo\Enums\MessageType;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 5) {
header('location:_admin4.php');
die();
}
$btn = Util::getPost('btn');
$genlist = Util::getPost('genlist', 'array_int');
$msg = Util::getPost('msg', 'string', '메시지');
$db = DB::db();
//NOTE: 왜 기능이 admin2와 admin4가 같이 있는가?
//NOTE: 왜 블럭 시 admin4에선 금쌀을 없애지 않는가?
switch ($btn) {
case "블럭 해제":
DB::db()->query('update general set block=0 where no IN %li', $genlist);
break;
case "1단계 블럭":
$date = TimeUtil::now();
$db = DB::db();
$db->query('update general set block=1,killturn=24 where no IN %li', $genlist);
//FIXME: subquery로 하는게 더 빠를 듯.
$uid = $db->queryFirstColumn('select owner from general where no IN %li', $genlist);
RootDB::db()->query('update member set block_num=block_num+1,block_date=%s where id IN %ls', $date, $uid);
break;
case "2단계 블럭":
$date = TimeUtil::now();
$db = DB::db();
$db->query('update general set block=2,killturn=24 where no IN %li', $genlist);
$uid = $db->queryFirstColumn('select owner from general where no IN %li', $genlist);
RootDB::db()->query('update member set block_num=block_num+1,block_date=%s where id IN %ls', $date, $uid);
break;
case "3단계 블럭":
$date = TimeUtil::now();
$db = DB::db();
$db->query('update general set block=3,killturn=24 where no IN %li', $genlist);
$uid = $db->queryFirstColumn('select owner from general where no IN %li', $genlist);
RootDB::db()->query('update member set block_num=block_num+1,block_date=%s where id IN %ls', $date, $uid);
break;
case "무한삭턴":
DB::db()->query('update general set killturn=8000 where no IN %li', $genlist);
break;
case "강제 사망":
$date = TimeUtil::now(true);
$db->update('general', [
'killturn' => 0,
'turntime' => $date,
], '`no` IN %li', $genlist);
$db->update('general_turn', [
'action' => '휴식',
'arg' => '{}',
'brief' => '휴식'
], 'general_id IN %li AND turn_idx = 0', $genlist);
break;
case "메세지 전달":
$date = TimeUtil::now();
$src = MessageTarget::buildQuick($session->generalID);
foreach($genlist as $generalID){
$msgObj = new Message(
MessageType::private,
$src,
MessageTarget::buildQuick($generalID),
$msg,
new \DateTime(),
new \DateTime('9999-12-31'),
[]
);
if ($msgObj) {
$msgObj->send(true);
}
}
break;
}
header('location:_admin4.php');
-14
View File
@@ -66,8 +66,6 @@ $sel2[$type2] = "selected";
<option <?= $sel[8] ?? '' ?> value=8>평무</option> <option <?= $sel[8] ?? '' ?> value=8>평무</option>
<option <?= $sel[9] ?? '' ?> value=9>평지</option> <option <?= $sel[9] ?? '' ?> value=9>평지</option>
<option <?= $sel[10] ?? '' ?> value=10>평Lv</option> <option <?= $sel[10] ?? '' ?> value=10>평Lv</option>
<option <?= $sel[11] ?? '' ?> value=11>접속률</option>
<option <?= $sel[12] ?? '' ?> value=12>단기접</option>
<option <?= $sel[13] ?? '' ?> value=13>보숙</option> <option <?= $sel[13] ?? '' ?> value=13>보숙</option>
<option <?= $sel[14] ?? '' ?> value=14>궁숙</option> <option <?= $sel[14] ?? '' ?> value=14>궁숙</option>
<option <?= $sel[15] ?? '' ?> value=15>기숙</option> <option <?= $sel[15] ?? '' ?> value=15>기숙</option>
@@ -105,8 +103,6 @@ $sel2[$type2] = "selected";
<table align=center width=1600 class="tb_layout bg0"> <table align=center width=1600 class="tb_layout bg0">
<tr class='bg1'> <tr class='bg1'>
<td align=center>국명</td> <td align=center>국명</td>
<td align=center>접률</td>
<td align=center>단접</td>
<td align=center>국력</td> <td align=center>국력</td>
<td align=center>장수</td> <td align=center>장수</td>
<td align=center>속령</td> <td align=center>속령</td>
@@ -147,8 +143,6 @@ SELECT
A.gold, A.gold,
A.rice, A.rice,
COUNT(B.nation) AS gennum, COUNT(B.nation) AS gennum,
ROUND(AVG(B.connect), 1) AS connect,
ROUND(AVG(B.con), 1) AS con,
ROUND(AVG(B.dex1)) AS dex1, ROUND(AVG(B.dex1)) AS dex1,
ROUND(AVG(B.dex2)) AS dex2, ROUND(AVG(B.dex2)) AS dex2,
ROUND(AVG(B.dex3)) AS dex3, ROUND(AVG(B.dex3)) AS dex3,
@@ -193,12 +187,6 @@ GROUP BY B.nation
case 10: case 10:
$query .= " order by avg(B.explevel) desc"; $query .= " order by avg(B.explevel) desc";
break; break;
case 11:
$query .= " order by avg(B.connect) desc";
break;
case 12:
$query .= " order by avg(B.con) desc";
break;
case 13: case 13:
$query .= " order by avg(B.dex1) desc"; $query .= " order by avg(B.dex1) desc";
break; break;
@@ -240,8 +228,6 @@ from city where nation=%i', $nation['nation']);
echo " echo "
<tr> <tr>
<td align=center style=background-color:{$nation['color']};color:" . newColor($nation['color']) . ";>{$nation['name']}</td> <td align=center style=background-color:{$nation['color']};color:" . newColor($nation['color']) . ";>{$nation['name']}</td>
<td align=center>&nbsp;{$nation['connect']}&nbsp;</td>
<td align=center>&nbsp;{$nation['con']}&nbsp;</td>
<td align=center>&nbsp;{$nation['power']}&nbsp;</td> <td align=center>&nbsp;{$nation['power']}&nbsp;</td>
<td align=center>&nbsp;{$gen['cnt']}&nbsp;</td> <td align=center>&nbsp;{$gen['cnt']}&nbsp;</td>
<td align=center>&nbsp;{$city['cnt']}&nbsp;</td> <td align=center>&nbsp;{$city['cnt']}&nbsp;</td>
+3 -1
View File
@@ -2,6 +2,8 @@
namespace sammo; namespace sammo;
use sammo\Enums\GeneralQueryMode;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -74,7 +76,7 @@ if (!$gen) {
$gen = $generalBasicList[0]['no']; $gen = $generalBasicList[0]['no'];
} }
$generalObj = General::createGeneralObjFromDB($gen); $generalObj = General::createGeneralObjFromDB($gen, null, GeneralQueryMode::FullWithAccessLog);
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
+16 -8
View File
@@ -16,10 +16,13 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("장수일람", 2); increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID); $me = $db->queryFirstRow(
'SELECT refresh_score,turntime FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner = %i', $userID
);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
@@ -102,7 +105,7 @@ if ($gameStor->isunited) {
6 => ['dedication', true], 6 => ['dedication', true],
7 => ['officer_level', true], 7 => ['officer_level', true],
8 => ['killturn', false], 8 => ['killturn', false],
9 => ['connect', true], 9 => ['refresh_score_total', true],
10 => ['experience', true], 10 => ['experience', true],
11 => ['personal', true], 11 => ['personal', true],
12 => ['special', true], 12 => ['special', true],
@@ -111,7 +114,12 @@ if ($gameStor->isunited) {
15 => ['npc', true], 15 => ['npc', true],
][$type]; ][$type];
$generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general order by %b %l', $orderKey, $orderDesc ? 'desc' : ''); $generalList = $db->query(
'SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,refresh_score_total
FROM `general` LEFT JOIN `general_access_log` ON general.no = general_access_log.general_id order by %b %l',
$orderKey,
$orderDesc ? 'desc' : ''
);
echo " echo "
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
@@ -163,7 +171,7 @@ if ($gameStor->isunited) {
$name = $name . '<br><small>(' . $ownerNameList[$general['owner']] . ')</small>'; $name = $name . '<br><small>(' . $ownerNameList[$general['owner']] . ')</small>';
} }
$general['connect'] = Util::round($general['connect'], -1); $general['refresh_score_total'] = Util::round($general['refresh_score_total'], -1);
$imageTemp = GetImageURL($general['imgsvr']); $imageTemp = GetImageURL($general['imgsvr']);
echo " echo "
@@ -192,8 +200,8 @@ if ($gameStor->isunited) {
<td align=center>$strength</td> <td align=center>$strength</td>
<td align=center>$intel</td> <td align=center>$intel</td>
<td align=center>{$general['killturn']}</td> <td align=center>{$general['killturn']}</td>
<td align=center>{$general['connect']}"; <td align=center>" . $general['refresh_score_total'] ?? 0;
echo "<br>【" . getConnect($general['connect']) . "】</td> echo "<br>【" . getRefreshScoreText($general['refresh_score_total'] ?? 0) . "】</td>
</tr>"; </tr>";
} }
echo " echo "
+6 -3
View File
@@ -13,10 +13,13 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['killturn', 'autorun_user', 'turnterm']); $gameStor->cacheValues(['killturn', 'autorun_user', 'turnterm']);
increaseRefresh("세력일람", 2); increaseRefresh("세력일람", 2);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT refresh_score, turntime FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
+15 -8
View File
@@ -2,6 +2,8 @@
namespace sammo; namespace sammo;
use sammo\Enums\GeneralAccessLogColumn;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -23,10 +25,10 @@ $online = [];
$curonline = getOnlineNum(); $curonline = getOnlineNum();
foreach ($log as $i => $value) { foreach ($log as $i => $value) {
$parse = Json::decode($value); $parse = Json::decode($value);
if(is_array($parse) === false){ if (is_array($parse) === false) {
continue; continue;
} }
if(count($parse) < 5){ if (count($parse) < 5) {
continue; continue;
} }
$date[$i] = $parse[0]; $date[$i] = $parse[0];
@@ -193,19 +195,24 @@ if ($admin['maxonline'] < $curonline) {
</td> </td>
</tr> </tr>
<?php <?php
$max_refresh = $db->queryFirstRow('SELECT sum(refresh) as refresh, sum(`connect`) as `connect` from general'); $totalRefresh = [
$max_refresh['name'] = '접속자 총합'; ...$db->queryFirstRow('SELECT sum(`refresh`) as `refresh`, sum(`refresh_score_total`) as `refresh_score_total` from general_access_log'),
'name' => '접속자 총합'
];
$refresh_result = array_merge([$max_refresh], $db->query('SELECT `name`,refresh,`connect` FROM general ORDER BY refresh DESC LIMIT 5')); $top5Refresh = $db->query(
'SELECT `name`, `log`.`refresh`, `refresh_score_total` FROM `general_access_log` AS `log`
INNER JOIN `general` ON `log`.`general_id` = `general`.`no` ORDER BY `log`.`refresh` DESC LIMIT 5'
);
foreach ($refresh_result as $i => $user) { foreach (array_merge([$totalRefresh], $top5Refresh) as $i => $user) {
$w = round($user['refresh'] / max(1, $max_refresh['refresh']) * 100, 1); $w = round($user['refresh'] / max(1, $totalRefresh['refresh']) * 100, 1);
$w2 = round(100 - $w, 1); $w2 = round(100 - $w, 1);
$color = getTrafficColor($w); $color = getTrafficColor($w);
?> ?>
<tr> <tr>
<td width=98 align=center><?= $user['name'] ?></td> <td width=98 align=center><?= $user['name'] ?></td>
<td width=98 align=center><?= $user['connect'] ?>(<?= $user['refresh'] ?>)</td> <td width=98 align=center><?= $user['refresh_score_total'] ?>(<?= $user['refresh'] ?>)</td>
<td width=798> <td width=798>
<?php if ($w == 0) : ?> <?php if ($w == 0) : ?>
<?php elseif ($w < 10) : ?> <?php elseif ($w < 10) : ?>
+9 -5
View File
@@ -2,6 +2,7 @@
namespace sammo; namespace sammo;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\RankColumn; use sammo\Enums\RankColumn;
include "lib.php"; include "lib.php";
@@ -21,12 +22,15 @@ $generalID = $session->generalID;
$me = $db->queryFirstRow('SELECT no,tournament,con,turntime from general where owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no,tournament,refresh_score,turntime FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id where owner=%i', $userID
);
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'turnterm', 'develcost']); $admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'turnterm', 'develcost']);
$turnTerm = $admin['turnterm']; $turnTerm = $admin['turnterm'];
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
@@ -107,7 +111,7 @@ if ($str3) {
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<?php if ($con == 1) { <?php if ($limitState == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!"); MessageBox("접속제한이 얼마 남지 않았습니다!");
} ?> } ?>
@@ -563,7 +567,7 @@ if ($str3) {
$tournamentRankerList = General::createGeneralObjListFromDB( $tournamentRankerList = General::createGeneralObjListFromDB(
$db->queryFirstColumn('SELECT general_id FROM rank_data WHERE `type`= %s ORDER BY value DESC LIMIT 40', $gameColumn->value), $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'], [$prizeColumn->value, $gameColumn->value, $winColumn->value, $drawColumn->value, $loseColumn->value, 'leadership', 'strength', 'intel', 'no', 'npc', 'name'],
0 GeneralQueryMode::Core
); );
usort($tournamentRankerList, function (General $lhs, General $rhs) use ($gameColumn, $winColumn, $drawColumn, $loseColumn) { usort($tournamentRankerList, function (General $lhs, General $rhs) use ($gameColumn, $winColumn, $drawColumn, $loseColumn) {
$result = - ($lhs->getRankVar($gameColumn) <=> $rhs->getRankVar($gameColumn)); $result = - ($lhs->getRankVar($gameColumn) <=> $rhs->getRankVar($gameColumn));
+2 -2
View File
@@ -211,7 +211,7 @@ $templates = new \League\Plates\Engine('templates');
$city['trade'] = "- "; $city['trade'] = "- ";
} }
$dbColumns = General::mergeQueryColumn(['npc', 'defence_train', 'no', 'picture', 'imgsvr', 'name', 'injury', 'leadership', 'strength', 'intel', 'officer_level', 'nation', 'crewtype', 'crew', 'train', 'atmos'], 2)[0]; $dbColumns = General::mergeQueryColumn(['npc', 'defence_train', 'no', 'picture', 'imgsvr', 'name', 'injury', 'leadership', 'strength', 'intel', 'officer_level', 'nation', 'crewtype', 'crew', 'train', 'atmos'])[0];
if ($showDetailedInfo) { if ($showDetailedInfo) {
$generals = $db->query( $generals = $db->query(
'SELECT %l from general where city=%i order by turntime', 'SELECT %l from general where city=%i order by turntime',
@@ -327,7 +327,7 @@ $templates = new \League\Plates\Engine('templates');
if ($ourGeneral && !$isNPC) { if ($ourGeneral && !$isNPC) {
$turnText = []; $turnText = [];
$generalObj = new General($general, null, null, null, null, null, false); $generalObj = new General($general, null, null, null, null, null, null, false);
foreach ($generalTurnList[$generalObj->getID()] as $turnRawIdx => $turn) { foreach ($generalTurnList[$generalObj->getID()] as $turnRawIdx => $turn) {
$turnIdx = $turnRawIdx + 1; $turnIdx = $turnRawIdx + 1;
$turnText[] = "{$turnIdx} : $turn"; $turnText[] = "{$turnIdx} : $turn";
+7 -4
View File
@@ -19,12 +19,15 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("암행부", 1); increaseRefresh("암행부", 1);
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,permission,penalty from general where owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no,nation,officer_level,refresh_score,turntime,belong,permission,penalty FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation=%i', $me['nation']); $nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation=%i', $me['nation']);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
@@ -45,7 +48,7 @@ $templates = new \League\Plates\Engine('templates');
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<?php if ($con == 1) { <?php if ($limitState == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!"); MessageBox("접속제한이 얼마 남지 않았습니다!");
} ?> } ?>
+6 -4
View File
@@ -97,7 +97,7 @@ if ($gameStor->isunited) {
7 => ['gold', true], 7 => ['gold', true],
8 => ['rice', true], 8 => ['rice', true],
9 => ['crew', true], 9 => ['crew', true],
10 => ['connect', true], 10 => ['refresh_score_total', true],
11 => ['personal', true], 11 => ['personal', true],
12 => ['special', true], 12 => ['special', true],
13 => ['special2', true], 13 => ['special2', true],
@@ -105,7 +105,9 @@ if ($gameStor->isunited) {
15 => ['npc', true], 15 => ['npc', true],
][$type]; ][$type];
$generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect,gold,rice,crew,belong from general where nation = %i order by %b %l', $me['nation'], $orderKey, $orderDesc ? 'desc' : ''); $generalList = $db->query(
'SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,refresh_score_total,gold,rice,crew,belong
FROM `general` LEFT JOIN `general_access_log` ON general.no = general_access_log.general_id where nation = %i order by %b %l', $me['nation'], $orderKey, $orderDesc ? 'desc' : '');
echo " echo "
<table align=center class='tb_layout bg0'> <table align=center class='tb_layout bg0'>
@@ -173,8 +175,8 @@ if ($gameStor->isunited) {
<td align=center>" . displayCharInfo($general['personal']) . "</td> <td align=center>" . displayCharInfo($general['personal']) . "</td>
<td align=center>" . displaySpecialDomesticInfo($general['special']) . " / " . displaySpecialWarInfo($general['special2']) . "</td> <td align=center>" . displaySpecialDomesticInfo($general['special']) . " / " . displaySpecialWarInfo($general['special2']) . "</td>
<td align=center>{$general['belong']}</td> <td align=center>{$general['belong']}</td>
<td align=center>{$general['connect']}"; <td align=center>". $general['refresh_score_total'] ?? 0;
echo "<br>(" . getConnect($general['connect']) . ")</td> echo "<br>(" . getRefreshScoreText($general['refresh_score_total'] ?? 0) . ")</td>
</tr>"; </tr>";
} }
echo " echo "
+19 -8
View File
@@ -2,6 +2,10 @@
namespace sammo; namespace sammo;
use sammo\Enums\GeneralAccessLogColumn;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\TableName;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -20,7 +24,7 @@ $gameStor->cacheValues(['turntime', 'opentime', 'autorun_user', 'npcmode']);
increaseRefresh("내정보", 1); increaseRefresh("내정보", 1);
$me = General::createGeneralObjFromDB($generalID); $me = General::createGeneralObjFromDB($generalID, null, GeneralQueryMode::FullWithAccessLog);
$myset = $me->getVar('myset'); $myset = $me->getVar('myset');
if ($myset > 0) { if ($myset > 0) {
@@ -29,7 +33,14 @@ if ($myset > 0) {
$submit = 'hidden'; $submit = 'hidden';
} }
$targetTime = addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, GameConst::$minTurnDieOnPrestart); $lastRefresh = $db->queryFirstField(
'SELECT %b FROM %b WHERE %b = %i',
GeneralAccessLogColumn::lastRefresh->value,
TableName::generalAccessLog->value,
GeneralAccessLogColumn::generalID->value, $generalID
);
$targetTime = addTurn($lastRefresh, $gameStor->turnterm, GameConst::$minTurnDieOnPrestart);
if ($gameStor->turntime <= $gameStor->opentime) { if ($gameStor->turntime <= $gameStor->opentime) {
//서버 가오픈시 할 수 있는 행동 //서버 가오픈시 할 수 있는 행동
if ($me->getNPCType() == 0 && $me->getNationID() == 0) { if ($me->getNPCType() == 0 && $me->getNationID() == 0) {
@@ -81,13 +92,13 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<div class="col">내 정 보<br><?= backButton() ?></div> <div class="col">내 정 보<br><?= backButton() ?></div>
</div> </div>
<div class="row gx-0"> <div class="row gx-0">
<div class="col col-12 col-md-6"> <div class="col col-12 col-lg-6">
<div class="row"> <div class="row">
<div class="col"><?php generalInfo($me); ?><?php generalInfo2($me); ?></div> <div class="col"><?php generalInfo($me); ?><?php generalInfo2($me); ?></div>
</div> </div>
</div> </div>
<div class="col col-12 col-md-6"> <div class="col col-12 col-lg-6">
<div class="row mx-0 gx-0"> <div class="row mx-0 gx-0">
<div class="col" style='padding-left:2ch;'> <div class="col" style='padding-left:2ch;'>
토너먼트 【 토너먼트 【
@@ -178,7 +189,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
</div> </div>
</div> </div>
</div> </div>
<div class="col col-12 col-md-6"> <div class="col col-12 col-lg-6">
<div class="row gx-0"> <div class="row gx-0">
<div class="col bg1 text-center"> <div class="col bg1 text-center">
<h4 style='color:skyblue'>개인 기록</h4> <h4 style='color:skyblue'>개인 기록</h4>
@@ -191,7 +202,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<button type="button" class="load_old_log btn btn-secondary" data-log_type="generalAction">이전 로그 불러오기</button> <button type="button" class="load_old_log btn btn-secondary" data-log_type="generalAction">이전 로그 불러오기</button>
</div> </div>
</div> </div>
<div class="col col-12 col-md-6"> <div class="col col-12 col-lg-6">
<div class="row gx-0"> <div class="row gx-0">
<div class="col bg1 text-center"> <div class="col bg1 text-center">
<h4 style='color:orange'>전투 기록</h4> <h4 style='color:orange'>전투 기록</h4>
@@ -205,7 +216,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
</div> </div>
</div> </div>
<div class="col col-12 col-md-6"> <div class="col col-12 col-lg-6">
<div class="row gx-0"> <div class="row gx-0">
<div class="col bg1 text-center"> <div class="col bg1 text-center">
<h4 style='color:skyblue'>장수 열전</h4> <h4 style='color:skyblue'>장수 열전</h4>
@@ -215,7 +226,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<?= formatHistoryToHTML(getGeneralHistoryLogAll($generalID)) ?> <?= formatHistoryToHTML(getGeneralHistoryLogAll($generalID)) ?>
</div> </div>
</div> </div>
<div class="col col-12 col-md-6"> <div class="col col-12 col-lg-6">
<div class="row gx-0"> <div class="row gx-0">
<div class="col bg1 text-center"> <div class="col bg1 text-center">
<h4 style='color:orange'>전투 결과</h4> <h4 style='color:orange'>전투 결과</h4>
+7 -5
View File
@@ -14,14 +14,16 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("토너먼트", 1); increaseRefresh("토너먼트", 1);
TurnExecutionHelper::executeAllCommand(); TurnExecutionHelper::executeAllCommand();
$me = $db->queryFirstRow('select no,tournament,con,turntime from general where owner=%i', $userID); $me = $db->queryFirstRow(
$generalID = $session->generalID; 'SELECT no,tournament,refresh_score,turntime from `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id where owner=%i', $userID
);
$admin = $gameStor->getValues(['tournament', 'phase', 'turnterm', 'tnmt_msg', 'tnmt_type', 'develcost', 'tnmt_trig']); $admin = $gameStor->getValues(['tournament', 'phase', 'turnterm', 'tnmt_msg', 'tnmt_type', 'develcost', 'tnmt_trig']);
$turnTerm = $admin['turnterm']; $turnTerm = $admin['turnterm'];
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
@@ -100,7 +102,7 @@ $globalBetTotal = array_sum($globalBet);
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<?php if ($con == 1) { <?php if ($limitState == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다! 제한량이 모자라다면 참여를 해보세요^^"); MessageBox("접속제한이 얼마 남지 않았습니다! 제한량이 모자라다면 참여를 해보세요^^");
} ?> } ?>
+6
View File
@@ -0,0 +1,6 @@
<?php
namespace sammo;
class ServerEnv extends ServerDefaultEnv {
//ServerEnv 기본값을 변경하고 싶다면 orig를 제거한 복사본을 만들고 수정
}
+75 -65
View File
@@ -5,6 +5,9 @@ namespace sammo;
use DateTime; use DateTime;
use Ds\Set; use Ds\Set;
use sammo\Enums\AuctionType; use sammo\Enums\AuctionType;
use sammo\Enums\GeneralAccessLogColumn;
use sammo\Enums\GeneralColumn;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\InheritanceKey; use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn; use sammo\Enums\RankColumn;
@@ -103,10 +106,9 @@ function GetImageURL($imgsvr, $filepath = '')
} }
/** /**
* @param null|int $con 장수의 벌점 * @param null|int $refreshScore 장수의 벌점
* @param null|int $conlimit 최대 벌점
*/ */
function checkLimit($con = null) function checkLimit($refreshScore = null)
{ {
$session = Session::getInstance(); $session = Session::getInstance();
if ($session->userGrade >= 4) { if ($session->userGrade >= 4) {
@@ -116,15 +118,15 @@ function checkLimit($con = null)
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
if ($con === null) { if ($refreshScore === null) {
$con = $db->queryFirstField('SELECT con FROM general WHERE `owner`=%i', Session::getUserID()); $refreshScore = $db->queryFirstField('SELECT refresh_score FROM general_access_log WHERE `general_id`=%i', Session::getGeneralID());
} }
$conlimit = $gameStor->conlimit; $refreshLimit = $gameStor->refreshLimit;
if ($con > $conlimit) { if ($refreshScore > $refreshLimit) {
return 2; return 2;
//접속제한 90%이면 경고문구 //접속제한 90%이면 경고문구
} elseif ($con > $conlimit * 0.9) { } elseif ($refreshScore > $refreshLimit * 0.9) {
return 1; return 1;
} else { } else {
return 0; return 0;
@@ -642,7 +644,7 @@ function generalInfo(General $generalObj)
$age = "<font color=red>{$age} 세</font>"; $age = "<font color=red>{$age} 세</font>";
} }
$connectCnt = round($generalObj->getVar('connect'), -1); $refreshScoreTotal = round($generalObj->getAccessLogVar(GeneralAccessLogColumn::refreshScoreTotal) ?? 0, -1);
$specialDomestic = $generalObj->getVar('special') === GameConst::$defaultSpecialDomestic $specialDomestic = $generalObj->getVar('special') === GameConst::$defaultSpecialDomestic
? "{$generalObj->getVar('specage')}세" ? "{$generalObj->getVar('specage')}세"
: "<font color=limegreen>" . displayiActionObjInfo($generalObj->getSpecialDomestic()) . "</font>"; : "<font color=limegreen>" . displayiActionObjInfo($generalObj->getSpecialDomestic()) . "</font>";
@@ -751,7 +753,7 @@ function generalInfo(General $generalObj)
<td style='text-align:center;' class='bg1'><b>부대</b></td> <td style='text-align:center;' class='bg1'><b>부대</b></td>
<td style='text-align:center;' colspan=3>{$troopInfo}</td> <td style='text-align:center;' colspan=3>{$troopInfo}</td>
<td style='text-align:center;' class='bg1'><b>벌점</b></td> <td style='text-align:center;' class='bg1'><b>벌점</b></td>
<td style='text-align:center;' colspan=5>" . getConnect($connectCnt) . " {$connectCnt}({$generalObj->getVar('con')})</td> <td style='text-align:center;' colspan=5>" . getRefreshScoreText($refreshScoreTotal) . " {$refreshScoreTotal}({$generalObj->getAccessLogVar(GeneralAccessLogColumn::refreshScore)})</td>
</tr> </tr>
</table>"; </table>";
} }
@@ -998,52 +1000,69 @@ function increaseRefresh($type = "", $cnt = 1)
$generalID = $session->generalID; $generalID = $session->generalID;
$userGrade = $session->userGrade; $userGrade = $session->userGrade;
$date = TimeUtil::now(); $dateObj = new \DateTimeImmutable();
$date = TimeUtil::format($dateObj, false);
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$isunited = $gameStor->isunited; $isunited = $gameStor->isunited;
$opentime = $gameStor->opentime; $opentime = $gameStor->opentime;
if($userGrade == 6){ if ($userGrade == 6) {
return; return;
} }
if($isunited == 2){ if ($isunited == 2) {
return; return;
} }
if(!$generalID){ if (!$generalID) {
return; return;
} }
if($opentime > $date){ if ($opentime > $date) {
return; return;
} }
$gameStor->refresh = $gameStor->refresh + $cnt; //TODO: +로 증가하는 값은 별도로 분리 $gameStor->refresh = $gameStor->refresh + $cnt; //TODO: +로 증가하는 값은 별도로 분리
$db->update('general', [ $db->insertUpdate('general_access_log', [
'lastrefresh' => $date, GeneralAccessLogColumn::generalID->value => $generalID,
'con' => $db->sqleval('con + %i', $cnt), GeneralAccessLogColumn::userID->value => $userID,
'connect' => $db->sqleval('connect + %i', $cnt), GeneralAccessLogColumn::lastRefresh->value => $date,
'refcnt' => $db->sqleval('refcnt + %i', $cnt), GeneralAccessLogColumn::refreshTotal->value => $cnt,
'refresh' => $db->sqleval('refresh + %i', $cnt) GeneralAccessLogColumn::refresh->value => $cnt,
], 'owner=%i', $userID); GeneralAccessLogColumn::refreshScore->value => $cnt,
GeneralAccessLogColumn::refreshScoreTotal->value => $cnt,
], [
GeneralAccessLogColumn::lastRefresh->value => $date,
GeneralAccessLogColumn::refreshTotal->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refreshTotal->value, $cnt),
GeneralAccessLogColumn::refresh->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refresh->value, $cnt),
GeneralAccessLogColumn::refreshScore->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refreshScore->value, $cnt),
GeneralAccessLogColumn::refreshScoreTotal->value => $db->sqleval('%b + %i', GeneralAccessLogColumn::refreshScoreTotal->value, $cnt),
]);
$date = date('Y_m_d H:i:s'); $serverPath = __DIR__;
$date2 = substr($date, 0, 10);
$online = getOnlineNum(); $serverID = UniqueConst::$serverID;
file_put_contents( $logPath = "{$serverPath}/logs/{$serverID}/api_log.db";
__DIR__ . "/logs/" . UniqueConst::$serverID . "/_{$date2}_refresh.txt",
sprintf( $logDB = FileDB::db($logPath, $serverPath . '/../f_install/sql/api_log.sql');
"%s, %s, %s, %s, %s, %d\n",
$date, $ip = $_SERVER['REMOTE_ADDR'] ?? 'local';
$session->userName, $date = date('Y-m-d H:i:s');
$session->generalName,
$session->ip, $logDB->insert('api_log', [
$type, 'user_id' => $session->userID,
$online 'ip' => $ip,
), 'date' => $date,
FILE_APPEND 'path' => "refresh",
); 'arg' => JSON::encode([
'type' => $type,
]),
'aux' => JSON::encode([
'generalID' => $generalID,
'generalName' => $session->generalName,
'userName' => $session->userName,
]),
]);
} }
function updateTraffic() function updateTraffic()
@@ -1054,9 +1073,6 @@ function updateTraffic()
$admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxonline', 'maxrefresh']); $admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxonline', 'maxrefresh']);
/** @var array{year:int,month:int,refresh:int,maxonline:int,maxrefresh:int} $admin */ /** @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');
if ($admin['maxrefresh'] < $admin['refresh']) { if ($admin['maxrefresh'] < $admin['refresh']) {
$admin['maxrefresh'] = $admin['refresh']; $admin['maxrefresh'] = $admin['refresh'];
} }
@@ -1067,22 +1083,7 @@ function updateTraffic()
$gameStor->maxrefresh = $admin['maxrefresh']; $gameStor->maxrefresh = $admin['maxrefresh'];
$gameStor->maxonline = $admin['maxonline']; $gameStor->maxonline = $admin['maxonline'];
$db->update('general', ['refresh' => 0], true); $db->update('general_access_log', ['refresh' => 0], true);
$date = TimeUtil::now();
//일시|년|월|총갱신|접속자|최다갱신자
file_put_contents(
__DIR__ . "/logs/" . UniqueConst::$serverID . "/_traffic.txt",
Json::encode([
$date,
$admin['year'],
$admin['month'],
$admin['refresh'],
$online,
$user['name'] . "(" . $user['refresh'] . ")"
]) . "\n",
FILE_APPEND
);
} }
function CheckOverhead() function CheckOverhead()
@@ -1090,13 +1091,13 @@ function CheckOverhead()
//서버정보 //서버정보
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
list($turnterm, $conlimit) = $gameStor->getValuesAsArray(['turnterm', 'conlimit']); [$turnterm, $refreshLimit] = $gameStor->getValuesAsArray(['turnterm', 'refreshLimit']);
$con = Util::round(pow($turnterm, 0.6) * 3) * 10; $nextRefreshLimit = Util::round(pow($turnterm, 0.6) * 3) * 10;
if ($con != $conlimit) { if ($nextRefreshLimit != $refreshLimit) {
$gameStor->conlimit = $con; $gameStor->refreshLimit = $nextRefreshLimit;
} }
} }
@@ -1200,7 +1201,16 @@ function updateOnline()
//동접수 //동접수
$startTurn = cutTurn($gameStor->turntime, $gameStor->turnterm, false); $startTurn = cutTurn($gameStor->turntime, $gameStor->turnterm, false);
$onlineUser = $db->query('SELECT no,name,nation FROM general WHERE lastrefresh >= %s AND npc < 2', $startTurn); $onlineUser = $db->query(
'SELECT %b, %b, %b FROM `general_access_log` as `log` INNER JOIN `general` ON `log`.%b = `general`.%b WHERE %b >= %s',
GeneralColumn::no->value,
GeneralColumn::name->value,
GeneralColumn::nation->value,
GeneralAccessLogColumn::generalID->value,
GeneralColumn::no->value,
GeneralAccessLogColumn::lastRefresh->value,
$startTurn
);
$onlineNum = count($onlineUser); $onlineNum = count($onlineUser);
$onlineNationUsers = Util::arrayGroupBy($onlineUser, 'nation'); $onlineNationUsers = Util::arrayGroupBy($onlineUser, 'nation');
@@ -1314,7 +1324,7 @@ function CheckHall($no)
["betrate", 'calc'], ["betrate", 'calc'],
]; ];
$generalObj = General::createGeneralObjFromDB($no, null, 2); $generalObj = General::createGeneralObjFromDB($no);
$ttw = $generalObj->getRankVar(RankColumn::ttw); $ttw = $generalObj->getRankVar(RankColumn::ttw);
$ttd = $generalObj->getRankVar(RankColumn::ttd); $ttd = $generalObj->getRankVar(RankColumn::ttd);
@@ -1711,7 +1721,7 @@ function deleteNation(General $lord, bool $applyDB): array
$lordID $lordID
), ),
['npc', 'owner', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'], ['npc', 'owner', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'],
1 GeneralQueryMode::Lite,
); );
$nationGeneralList[$lordID] = $lord; $nationGeneralList[$lordID] = $lord;
@@ -1728,7 +1738,7 @@ function deleteNation(General $lord, bool $applyDB): array
// 전 장수 재야로 // 전 장수 재야로
foreach ($nationGeneralList as $general) { foreach ($nationGeneralList as $general) {
if($general->getNPCType() < 2){ if ($general->getNPCType() < 2) {
$general->setAuxVar( $general->setAuxVar(
InheritanceKey::max_belong->value, InheritanceKey::max_belong->value,
max( max(
+49 -12
View File
@@ -133,19 +133,19 @@ function getNationType(?string $type) {
} }
function getConnect($con) { function getRefreshScoreText($score) {
if($con < 50) $conname = '안함'; if($score < 50) $scoreName = '안함';
elseif($con < 100) $conname = '무관심'; elseif($score < 100) $scoreName = '무관심';
elseif($con < 200) $conname = '가끔'; elseif($score < 200) $scoreName = '가끔';
elseif($con < 400) $conname = '보통'; elseif($score < 400) $scoreName = '보통';
elseif($con < 800) $conname = '자주'; elseif($score < 800) $scoreName = '자주';
elseif($con < 1600) $conname = '열심'; elseif($score < 1600) $scoreName = '열심';
elseif($con < 3200) $conname = '중독'; elseif($score < 3200) $scoreName = '중독';
elseif($con < 6400) $conname = '폐인'; elseif($score < 6400) $scoreName = '폐인';
elseif($con < 12800) $conname = '경고'; elseif($score < 12800) $scoreName = '경고';
else $conname = '헐...'; else $scoreName = '헐...';
return $conname; return $scoreName;
} }
function getNationType2(?string $type) { function getNationType2(?string $type) {
@@ -326,6 +326,41 @@ function buildGeneralSpecialWarClass(?string $type):BaseSpecial{
return $obj; return $obj;
} }
function getActionCrewTypeClass(?string $type){
if($type === null || $type === ''){
$type = 'None';
}
static $basePath = __NAMESPACE__.'\\ActionCrewType\\';
$classPath = ($basePath.$type);
if(class_exists($classPath)){
return $classPath;
}
$classPath = ($basePath.'che_'.$type);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$type}은 올바른 병종 효과가 아님");
}
function buildActionCrewTypeClass(?string $type):iAction{
static $cache = [];
if($type === null){
$type = 'None';
}
if(key_exists($type, $cache)){
return $cache[$type];
}
$class = getActionCrewTypeClass($type);
$obj = new $class();
$cache[$type]= $obj;
return $obj;
}
function getGeneralCommandClass(?string $type){ function getGeneralCommandClass(?string $type){
if($type === null || $type === ''){ if($type === null || $type === ''){
$type = '휴식'; $type = '휴식';
@@ -542,6 +577,8 @@ function getExpLevel($experience) {
$level = Util::toInt(sqrt($experience/10)); $level = Util::toInt(sqrt($experience/10));
} }
$level = Util::clamp($level, 0, GameConst::$maxLevel);
return $level; return $level;
} }
+34 -210
View File
@@ -202,8 +202,10 @@ function preUpdateMonthly()
$admin = $gameStor->getValues(['startyear', 'year', 'month']); $admin = $gameStor->getValues(['startyear', 'year', 'month']);
//접률감소, 건국제한-1 //접률감소, 건국제한-1
$db->update('general_access_log', [
'refresh_score_total' => $db->sqleval('floor(refresh_score_total*0.99)'),
], true);
$db->update('general', [ $db->update('general', [
'connect' => $db->sqleval('floor(connect*0.99)'),
'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'), 'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'),
], true); ], true);
//전략제한-1, 외교제한-1, 세율동기화 //전략제한-1, 외교제한-1, 세율동기화
@@ -301,7 +303,6 @@ function postUpdateMonthly(RandUtil $rng)
WHERE g.nation = A.nation) WHERE g.nation = A.nation)
+(select round(sum(dex1+dex2+dex3+dex4+dex5)/1000) from general where nation=A.nation) +(select round(sum(dex1+dex2+dex3+dex4+dex5)/1000) from general where nation=A.nation)
+(select round(sum(experience+dedication)/100) from general where nation=A.nation) +(select round(sum(experience+dedication)/100) from general where nation=A.nation)
+(select round(avg(connect)) from general where nation=A.nation)
)/10) )/10)
as power, as power,
(select sum(crew) from general where nation=A.nation) as totalCrew (select sum(crew) from general where nation=A.nation) as totalCrew
@@ -423,8 +424,6 @@ function postUpdateMonthly(RandUtil $rng)
if ($admin['year'] >= $admin['startyear'] + 2) { if ($admin['year'] >= $admin['startyear'] + 2) {
checkWander($rng); checkWander($rng);
} }
// 작위 업데이트
updateNationState();
updateGeneralNumber(); updateGeneralNumber();
refreshNationStaticInfo(); refreshNationStaticInfo();
// 천통여부 검사 // 천통여부 검사
@@ -467,209 +466,6 @@ function checkWander(RandUtil $rng)
} }
} }
function updateNationState()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['killturn', 'year', 'month', 'fiction', 'startyear', 'show_img_level', 'turnterm', 'turntime']);
$year = $admin['year'];
$month = $admin['month'];
$startYear = $admin['startyear'];
$nationCityCounts = [];
foreach($db->queryAllLists('SELECT nation, count(*) FROM city WHERE LEVEL>=4 GROUP BY nation') as [$nationID, $cityCnt]){
$nationCityCounts[$nationID] = $cityCnt;
}
$nationLevelByCityCnt = [
0, //방랑군
1, //호족
2, //군벌
5, //주자사
8, //주목
11, //공
16, //왕
21, //황제
];
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
//TODO: level이 진관수이소중대특 체계를 벗어날 수 있음
$nationID = $nation['nation'];
$cityCnt = $nationCityCounts[$nationID] ?? 0;
/** @var int */
$nationlevel = 0;
foreach($nationLevelByCityCnt as $cmpNationLevel => $cmpCityCnt){
if($cityCnt < $cmpCityCnt){
break;
}
$nationlevel = $cmpNationLevel;
}
if ($nationlevel > $nation['level']) {
$levelDiff = $nationlevel - $nation['level'];
$oldLevel = $nation['level'];
$nation['level'] = $nationlevel;
$updateVals = [
'level' => $nationlevel,
'gold' => $db->sqleval('gold + %i', $nationlevel * 1000),
'rice' => $db->sqleval('rice + %i', $nationlevel * 1000),
];
$nationName = $nation['name'];
$lordName = $db->queryFirstField('SELECT name FROM general WHERE nation = %i AND officer_level = 12', $nationID);
$oldNationLevelText = getNationLevel($oldLevel);
$nationLevelText = getNationLevel($nationlevel);
$logger = new ActionLogger(0, $nationID, $year, $month, false);
$josaYi = JosaUtil::pick($lordName, '이');
switch ($nationlevel) {
case 7: //황제
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><D><b>{$nationName}</b></> {$oldNationLevelText} <Y>{$lordName}</>{$josaYi} <C>{$nationLevelText}</>{$josaRo} 옹립되었습니다.");
$logger->pushNationalHistoryLog("<D><b>{$nationName}</b></> {$oldNationLevelText} <Y>{$lordName}</>{$josaYi} <C>{$nationLevelText}</>{$josaRo} 옹립");
$auxVal = Json::decode($nation['aux']);
$auxVal['can_국기변경'] = 1;
$auxVal['can_국호변경'] = 1;
$updateVals['aux'] = Json::encode($auxVal);
break;
case 6: //왕
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 책봉되었습니다.");
$logger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 책봉");
break;
case 5: //공
case 4: //주목
case 3: //주자사
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 임명되었습니다.");
$logger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 임명됨");
break;
case 2: //군벌
$josaRa = JosaUtil::pick($nationName, '라');
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><Y>{$lordName}</>{$josaYi} 독립하여 <D><b>{$nationName}</b></>{$josaRa}는 <C>$nationLevelText</>{$josaRo} 나섰습니다.");
$logger->pushNationalHistoryLog("<Y>{$lordName}</>{$josaYi} 독립하여 <D><b>{$nationName}</b></>{$josaRa}는 <C>$nationLevelText</>{$josaRo} 나서다");
break;
}
$db->update('nation', $updateVals, 'nation=%i', $nation['nation']);
$logger->flush();
$turnRows = [];
foreach (Util::range(getNationChiefLevel($nation['level']), 12) as $chiefLevel) {
foreach (Util::range(GameConst::$maxChiefTurn) as $turnIdx) {
$turnRows[] = [
'nation_id' => $nation['nation'],
'officer_level' => $chiefLevel,
'turn_idx' => $turnIdx,
'action' => '휴식',
'arg' => null,
'brief' => '휴식'
];
}
}
$db->insertIgnore('nation_turn', $turnRows);
if ($levelDiff) {
//유니크 아이템 하나 돌리자
$targetKillTurn = $admin['killturn'];
$targetKillTurn -= 24 * 60 / $admin['turnterm'];
$nationGenIDList = $db->queryFirstColumn(
'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2',
$nation['nation'],
$targetKillTurn
);
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux'], 2);
$chiefID = null;
$uniqueLotteryWeightList = [];
$relYear = $year - $startYear;
$maxTrialCountByYear = 1;
foreach (GameConst::$maxUniqueItemLimit as $tmpVals) {
[$targetYear, $targetTrialCnt] = $tmpVals;
if ($relYear < $targetYear) {
break;
}
$maxTrialCountByYear = $targetTrialCnt;
}
foreach ($nationGenList as $nationGen) {
if ($nationGen->getVar('officer_level') == 12) {
$chiefID = $nationGen->getID();
}
$trialCnt = min($maxTrialCountByYear, count(GameConst::$allItems));
foreach ($nationGen->getItems() as $item) {
if (!$item->isBuyable()) {
$trialCnt -= 1;
}
}
if ($trialCnt <= 0) {
continue;
}
$score = $nationGen->getVar('belong') + 10;
if ($nationGen->getVar('officer_level') == 12) {
$score += 60;
} else if ($nationGen->getVar('officer_level') == 11) {
$score += 30;
} else if ($nationGen->getVar('officer_level') > 4) {
$score += 15;
}
$score *= 2 ** $trialCnt;
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
}
$nationLevelUpRNG = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'nationLevelUp',
$year,
$month,
$nationID
)));
foreach (Util::range($levelDiff) as $idx) {
if (!$uniqueLotteryWeightList) {
break;
}
/** @var General */
$winnerObj = $nationLevelUpRNG->choiceUsingWeightPair($uniqueLotteryWeightList);
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
$givenUniqueRNG = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'givenUnique',
$year,
$month,
$nationID,
$winnerObj->getID(),
)));
giveRandomUniqueItem($givenUniqueRNG, $winnerObj, '작위보상');
$winnerObj->applyDB($db);
}
if ($chiefID) {
$chiefObj = General::createGeneralObjFromDB($chiefID, ['belong', 'npc', 'aux'], 2);
$chiefObj->increaseInheritancePoint(InheritanceKey::unifier, 250 * $levelDiff);
$chiefObj->applyDB($db);
}
}
}
}
}
function checkStatistic() function checkStatistic()
{ {
$db = DB::db(); $db = DB::db();
@@ -902,7 +698,7 @@ function checkEmperior()
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']); $admin = $gameStor->getValues(['year', 'month', 'isunited', 'refreshLimit']);
if ($admin['isunited'] != 0) { if ($admin['isunited'] != 0) {
return; return;
} }
@@ -964,7 +760,7 @@ function checkEmperior()
} }
$gameStor->isunited = 2; $gameStor->isunited = 2;
$gameStor->conlimit = $gameStor->conlimit * 100; $gameStor->refreshLimit = $gameStor->refreshLimit * 100;
foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) { foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
CheckHall($hallGeneralNo); CheckHall($hallGeneralNo);
@@ -976,7 +772,7 @@ function checkEmperior()
$chiefs = Util::convertArrayToDict( $chiefs = Util::convertArrayToDict(
$db->query( $db->query(
'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5', 'SELECT no,npc,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5',
$nationID $nationID
), ),
'officer_level' 'officer_level'
@@ -1113,6 +909,34 @@ function checkEmperior()
//연감 월결산 //연감 월결산
LogHistory(); LogHistory();
$availableInvaderGame = false;
foreach(CityConst::all() as $city){
if($city->level == 4){
$availableInvaderGame = true;
break;
}
}
if($availableInvaderGame){
$invaderMsgCnt = 2;
foreach(range(12, 5, -1) as $chiefLevel){
if(!key_exists($chiefLevel, $chiefs)){
continue;
}
$targetChief = $chiefs[$chiefLevel];
if($targetChief['npc'] >= 2){
continue;
}
$invaderMsgs = RaiseInvaderMessage::buildRaiseInvaderMessage($targetChief['no']);
foreach($invaderMsgs as $invaderMsg){
$invaderMsg->send();
}
$invaderMsgCnt--;
if($invaderMsgCnt <= 0){
break;
}
}
}
} }
function updateMaxDomesticCritical(General $general, $score) function updateMaxDomesticCritical(General $general, $score)
+1 -1
View File
@@ -383,7 +383,7 @@ function disaster(RandUtil $rng) {
$generalList = array_map( $generalList = array_map(
function($rawGeneral) use ($city, $year, $month){ function($rawGeneral) use ($city, $year, $month){
return new General($rawGeneral, null, $city, null, $year, $month, false); return new General($rawGeneral, null, null, $city, null, $year, $month, false);
}, },
$generalListByCity[$city['city']]??[] $generalListByCity[$city['city']]??[]
); );
+2 -2
View File
@@ -39,8 +39,8 @@ if ($session->userGrade < 5 && !$allowReset) {
<body> <body>
<div class="container"> <div class="container">
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 리셋</h1> <h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 리셋</h1>
<div class="row justify-content-md-center"> <div class="row justify-content-lg-center">
<div class="col col-lg-8"> <div class="col col-lg-8">
<div class="card" id="game_form_card"> <div class="card" id="game_form_card">
+2 -2
View File
@@ -32,8 +32,8 @@ if ($session->userGrade == 5) {
<body> <body>
<div class="container" style="min-width:720px;"> <div class="container" style="min-width:720px;">
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 리셋</h1> <h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 리셋</h1>
<div class="row justify-content-md-center"> <div class="row justify-content-lg-center">
<div class="col col-lg-8"> <div class="col col-lg-8">
<div class="card" id="db_form_card"> <div class="card" id="db_form_card">
+7 -4
View File
@@ -17,10 +17,13 @@ $text = Util::getPost('text');
increaseRefresh("회의실", 1); increaseRefresh("회의실", 1);
$me = $db->queryFirstRow('SELECT no, nation, name, officer_level, permission, con, turntime, belong, penalty, `picture`,`imgsvr` FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no, nation, name, officer_level, permission, refresh_score, turntime, belong, penalty, `picture`,`imgsvr` FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -50,7 +53,7 @@ if($permission < 0){
'result'=>false, 'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.' 'reason'=>'국가에 소속되어있지 않습니다.'
]); ]);
} }
else if ($isSecretBoard && $permission < 2) { else if ($isSecretBoard && $permission < 2) {
Json::die([ Json::die([
+7 -4
View File
@@ -16,10 +16,13 @@ $text = Util::getPost('text');
increaseRefresh("회의실", 1); increaseRefresh("회의실", 1);
$me = $db->queryFirstRow('SELECT no, nation, name, officer_level, permission, con, turntime, belong, penalty FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no, nation, name, officer_level, permission, refresh_score, turntime, belong, penalty FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -58,7 +61,7 @@ if($permission < 0){
'result'=>false, 'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.' 'reason'=>'국가에 소속되어있지 않습니다.'
]); ]);
} }
else if ($isSecretBoard && $permission < 2) { else if ($isSecretBoard && $permission < 2) {
Json::die([ Json::die([
+7 -5
View File
@@ -16,11 +16,14 @@ $isSecretBoard = Util::getPost('isSecret', 'bool', false);
increaseRefresh("회의실", 1); increaseRefresh("회의실", 1);
$me = $db->queryFirstRow('SELECT no, nation, officer_level, permission, con, turntime, belong, penalty FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no, nation, officer_level, permission, refresh_score, turntime, belong, penalty FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -33,7 +36,7 @@ if($permission < 0){
'result'=>false, 'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.' 'reason'=>'국가에 소속되어있지 않습니다.'
]); ]);
} }
else if ($isSecretBoard && $permission < 2) { else if ($isSecretBoard && $permission < 2) {
Json::die([ Json::die([
@@ -72,4 +75,3 @@ Json::die([
'articles'=>$articles, 'articles'=>$articles,
'reason'=>'success' 'reason'=>'success'
]); ]);
+6 -3
View File
@@ -17,10 +17,13 @@ $letterNo = Util::getPost('letterNo', 'int');
increaseRefresh("외교부", 1); increaseRefresh("외교부", 1);
$me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no, name, nation, officer_level, permission, refresh_score, turntime, belong, penalty, picture, imgsvr FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
+7 -5
View File
@@ -16,11 +16,14 @@ $isSecretBoard = Util::getPost('isSecret', 'bool', false);
increaseRefresh("외교부", 1); increaseRefresh("외교부", 1);
$me = $db->queryFirstRow('SELECT no, nation, officer_level, permission, con, turntime, belong, penalty FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no, nation, officer_level, permission, refresh_score, turntime, belong, penalty FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -33,7 +36,7 @@ if($permission < 0){
'result'=>false, 'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.' 'reason'=>'국가에 소속되어있지 않습니다.'
]); ]);
} }
$letters = []; $letters = [];
@@ -83,4 +86,3 @@ Json::die([
'myNationID'=>$me['nation'], 'myNationID'=>$me['nation'],
'reason'=>'success' 'reason'=>'success'
]); ]);
+6 -3
View File
@@ -22,10 +22,13 @@ $reason = Util::getPost('reason', 'string', '');
increaseRefresh("외교부", 1); increaseRefresh("외교부", 1);
$me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no, name, nation, officer_level, permission, refresh_score, turntime, belong, penalty, picture, imgsvr FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
+6 -3
View File
@@ -17,10 +17,13 @@ $letterNo = Util::getPost('letterNo', 'int');
increaseRefresh("외교부", 1); increaseRefresh("외교부", 1);
$me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no, name, nation, officer_level, permission, refresh_score, turntime, belong, penalty, picture, imgsvr FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
+6 -3
View File
@@ -24,10 +24,13 @@ if($prevNo < 1){
$prevNo = null; $prevNo = null;
} }
$me = $db->queryFirstRow('SELECT no, name, nation, officer_level, permission, con, turntime, belong, penalty, picture, imgsvr FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no, name, nation, officer_level, permission, refresh_score, turntime, belong, penalty, picture, imgsvr FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
+7 -4
View File
@@ -33,12 +33,15 @@ if($generalID <= 0 || $reqTo <= 0){
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,permission,penalty from general where owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no,nation,officer_level,refresh_score,turntime,belong,permission,penalty FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$nationID = $me['nation']; $nationID = $me['nation'];
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한입니다.' 'reason'=>'접속 제한입니다.'
@@ -61,7 +64,7 @@ if($generalID !== $targetID){
'reason'=>'권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.' 'reason'=>'권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.'
]); ]);
} }
if($testGeneralNationID !== $nationID){ if($testGeneralNationID !== $nationID){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
+2 -1
View File
@@ -1,6 +1,7 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\MessageType; use sammo\Enums\MessageType;
include "lib.php"; include "lib.php";
@@ -50,7 +51,7 @@ else{
'troop','officer_level','npc','picture','imgsvr', 'troop','officer_level','npc','picture','imgsvr',
'permission','penalty','belong', 'crewtype', 'permission','penalty','belong', 'crewtype',
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'aux', 'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'aux',
], 1); ], GeneralQueryMode::Lite);
if($general instanceof DummyGeneral){ if($general instanceof DummyGeneral){
Json::die([ Json::die([
+7
View File
@@ -1,6 +1,8 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Enums\GeneralAccessLogColumn;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -86,6 +88,11 @@ $db->update('general', [
'owner'=>$userID, 'owner'=>$userID,
'aux'=>Json::encode($genAux) 'aux'=>Json::encode($genAux)
], 'owner <= 0 AND npc = 2 AND no = %i', $pick); ], 'owner <= 0 AND npc = 2 AND no = %i', $pick);
$db->insertIgnore('general_access_log', [
GeneralAccessLogColumn::generalID->value => $generalID,
GeneralAccessLogColumn::userID->value => $userID,
GeneralAccessLogColumn::lastRefresh->value => $now,
]);
if(!$db->affectedRows()){ if(!$db->affectedRows()){
Json::die([ Json::die([
+4 -1
View File
@@ -39,7 +39,10 @@ if (!$data || !is_array($data)) {
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow('SELECT no, name, npc, nation, city, officer_level, con, turntime, belong, permission, penalty FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no, name, npc, nation, city, officer_level, refresh_score, turntime, belong, permission, penalty FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$nationID = $me['nation']; $nationID = $me['nation'];
+277 -220
View File
@@ -1,4 +1,5 @@
<?php <?php
namespace sammo; namespace sammo;
use Ds\Map; use Ds\Map;
@@ -15,48 +16,48 @@ $userID = Session::getUserID();
increaseRefresh("시뮬레이터", 0); increaseRefresh("시뮬레이터", 0);
$query = Util::getPost('query'); $query = Util::getPost('query');
if($query === null){ if ($query === null) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'입력값이 없습니다.' 'reason' => '입력값이 없습니다.'
]); ]);
} }
$action = Util::getPost('action'); $action = Util::getPost('action');
if($action === null || !in_array($action, ['reorder', 'battle'])){ if ($action === null || !in_array($action, ['reorder', 'battle'])) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'원하는 동작이 지정되지 않았습니다.' 'reason' => '원하는 동작이 지정되지 않았습니다.'
]); ]);
} }
$query = Json::decode($query); $query = Json::decode($query);
if($query === null){ if ($query === null) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'올바르지 않은 JSON입니다.' 'reason' => '올바르지 않은 JSON입니다.'
]); ]);
} }
$defaultCheck = [ $defaultCheck = [
'required'=>[ 'required' => [
'attackerGeneral', 'attackerCity', 'attackerNation', 'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation', 'defenderGenerals', 'defenderCity', 'defenderNation',
'year', 'month', 'repeatCnt' 'year', 'month', 'repeatCnt'
], ],
'integer'=>[ 'integer' => [
'year','month','repeatCnt' 'year', 'month', 'repeatCnt'
], ],
'between'=>[ 'between' => [
['month', [1, 12]] ['month', [1, 12]]
], ],
'in'=>[ 'in' => [
['repeatCnt', [1, 1000]] ['repeatCnt', [1, 1000]]
], ],
'min'=>[ 'min' => [
['year', 0] ['year', 0]
], ],
'array'=>[ 'array' => [
'attackerGeneral', 'attackerCity', 'attackerNation', 'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation' 'defenderGenerals', 'defenderCity', 'defenderNation'
], ],
@@ -64,10 +65,10 @@ $defaultCheck = [
$v = new Validator($query); $v = new Validator($query);
$v->rules($defaultCheck); $v->rules($defaultCheck);
if(!$v->validate()){ if (!$v->validate()) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>$v->errorStr() 'reason' => $v->errorStr()
]); ]);
} }
@@ -86,20 +87,110 @@ $rawDefenderNation = $query['defenderNation'];
$warSeed = $query['seed'] ?? ''; $warSeed = $query['seed'] ?? '';
$cityCheck = [
'required' => [
'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',
],
'numeric' => [
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
],
'integer' => [
'city', 'nation', 'supply',
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'state',
],
'min' => [
['def', 0],
['wall', 0],
['trust', 0],
['pop', 0],
['comm', 0],
['secu', 0],
['city', 1],
['nation', 0]
],
'in' => [
['level', array_keys(getCityLevelList())]
]
];
$v = new Validator($rawAttackerCity);
$v->rules($cityCheck);
if (!$v->validate()) {
Json::die([
'result' => false,
'reason' => '[출병도시]' . $v->errorStr()
]);
}
$v = new Validator($rawDefenderCity);
$v->rules($cityCheck);
if (!$v->validate()) {
Json::die([
'result' => false,
'reason' => '[수비도시]' . $v->errorStr()
]);
}
$nationCheck = [
'required' => [
'type', 'tech', 'level', 'capital',
'nation', 'name', 'gold', 'rice', 'gennum'
],
'integer' => [
'level', 'capital', 'nation', 'gennum',
],
'numeric' => [
'tech', 'gold', 'rice'
],
'min' => [
['tech', 0],
['gold', 0],
['rice', 0],
['gennum', 1],
],
'in' => [
['type', GameConst::$availableNationType],
['level', array_keys(getNationLevelList())]
]
];
$v = new Validator($rawAttackerNation);
$v->rules($nationCheck);
if (!$v->validate()) {
Json::die([
'result' => false,
'reason' => '[출병국]' . $v->errorStr()
]);
}
$v = new Validator($rawDefenderNation);
$v->rules($nationCheck);
if (!$v->validate()) {
Json::die([
'result' => false,
'reason' => '[수비국]' . $v->errorStr()
]);
}
$generalCheck = [ $generalCheck = [
'required'=>[ 'required' => [
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train', 'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item', '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', 'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'recent_war', 'warnum', 'killnum', 'killcrew', 'recent_war', 'warnum', 'killnum', 'killcrew',
], ],
'integer'=>[ 'integer' => [
'no', 'nation', 'crew', 'crewtype', 'atmos', 'train', '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', 'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'warnum', 'killnum', 'killcrew', 'warnum', 'killnum', 'killcrew',
], ],
'min'=>[ 'min' => [
['no', 1], ['no', 1],
['nation', 1], ['nation', 1],
['crew', 0], ['crew', 0],
@@ -118,14 +209,14 @@ $generalCheck = [
['killnum', 0], ['killnum', 0],
['killcrew', 0], ['killcrew', 0],
], ],
'between'=>[ 'between' => [
['train', [40, GameConst::$maxTrainByWar]], ['train', [40, GameConst::$maxTrainByWar]],
['atmos', [40, GameConst::$maxAtmosByWar]], ['atmos', [40, GameConst::$maxAtmosByWar]],
['explevel', [0, 300]], ['explevel', [0, 300]],
['injury', [0, 80]], ['injury', [0, 80]],
['officer_level', [1, 12]] ['officer_level', [1, 12]]
], ],
'in'=>[ 'in' => [
['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)], ['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)],
['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)], ['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)],
['crewtype', array_keys(GameUnitConst::all())], ['crewtype', array_keys(GameUnitConst::all())],
@@ -134,11 +225,11 @@ $generalCheck = [
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])], ['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])], ['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
], ],
'array'=>['inheritBuff'], 'array' => ['inheritBuff'],
]; ];
$inheritBuffCheck = [ $inheritBuffCheck = [
'between'=>[ 'between' => [
[TriggerInheritBuff::WAR_AVOID_RATIO, [0, 5]], [TriggerInheritBuff::WAR_AVOID_RATIO, [0, 5]],
[TriggerInheritBuff::WAR_CRITICAL_RATIO, [0, 5]], [TriggerInheritBuff::WAR_CRITICAL_RATIO, [0, 5]],
[TriggerInheritBuff::WAR_MAGIC_TRIAL_PROB, [0, 5]], [TriggerInheritBuff::WAR_MAGIC_TRIAL_PROB, [0, 5]],
@@ -149,49 +240,67 @@ $inheritBuffCheck = [
] ]
]; ];
if(!$warSeed){
$warSeed = bin2hex(random_bytes(16));
}
else {
$repeatCnt = 1;
}
$tmpRNG = new RandUtil(new LiteHashDRBG($warSeed));
$v = new Validator($rawAttacker); $v = new Validator($rawAttacker);
$v->rules($generalCheck); $v->rules($generalCheck);
if(!$v->validate()){ if (!$v->validate()) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'[출병자]'.$v->errorStr() 'reason' => '[출병자]' . $v->errorStr()
]); ]);
} }
$rawAttacker['aux'] = []; $rawAttacker['aux'] = [];
if(key_exists('inheritBuff', $rawAttacker)){ if (key_exists('inheritBuff', $rawAttacker)) {
$v = new Validator($rawAttacker['inheritBuff']); $v = new Validator($rawAttacker['inheritBuff']);
$v->rules($inheritBuffCheck); $v->rules($inheritBuffCheck);
if(!$v->validate()){ if (!$v->validate()) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'[출병자]'.$v->errorStr() 'reason' => '[출병자]' . $v->errorStr()
]); ]);
} }
$rawAttacker['aux']['inheritBuff'] = $rawAttacker['inheritBuff']; $rawAttacker['aux']['inheritBuff'] = $rawAttacker['inheritBuff'];
} }
$rawAttacker['aux'] = Json::encode($rawAttacker['aux']); $rawAttacker['aux'] = Json::encode($rawAttacker['aux']);
$rawAttacker['owner'] = 0; $rawAttacker['owner'] = 0;
$attackerGeneral = new General($rawAttacker, extractRankVar($rawAttacker), null, $rawAttackerCity, $rawAttackerNation, $year, $month);
$attacker = new WarUnitGeneral(
$tmpRNG,
$attackerGeneral,
$rawAttackerNation,
true
);
/** @var WarUnit[] */
$defenderList = []; $defenderList = [];
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
foreach ($rawDefenderList as $idx => $rawDefenderGeneral) {
$v = new Validator($rawDefenderGeneral); $v = new Validator($rawDefenderGeneral);
$v->rules($generalCheck); $v->rules($generalCheck);
if(!$v->validate()){ if (!$v->validate()) {
$idx+=1; $idx += 1;
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>"[수비자{$idx}]".$v->errorStr() 'reason' => "[수비자{$idx}]" . $v->errorStr()
]); ]);
} }
$rawDefenderGeneral['aux'] = []; $rawDefenderGeneral['aux'] = [];
if(key_exists('inheritBuff', $rawDefenderGeneral)){ if (key_exists('inheritBuff', $rawDefenderGeneral)) {
$v = new Validator($rawDefenderGeneral['inheritBuff']); $v = new Validator($rawDefenderGeneral['inheritBuff']);
$v->rules($inheritBuffCheck); $v->rules($inheritBuffCheck);
if(!$v->validate()){ if (!$v->validate()) {
$idx+=1; $idx += 1;
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>"[수비자{$idx}]".$v->errorStr() 'reason' => "[수비자{$idx}]" . $v->errorStr()
]); ]);
} }
$rawDefenderGeneral['aux']['inheritBuff'] = $rawDefenderGeneral['inheritBuff']; $rawDefenderGeneral['aux']['inheritBuff'] = $rawDefenderGeneral['inheritBuff'];
@@ -199,135 +308,54 @@ foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
$rawDefenderGeneral['aux'] = Json::encode($rawDefenderGeneral['aux']); $rawDefenderGeneral['aux'] = Json::encode($rawDefenderGeneral['aux']);
$rawDefenderGeneral['owner'] = 0; $rawDefenderGeneral['owner'] = 0;
$defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true); $defenderGeneral = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), null, $rawDefenderCity, $rawAttackerNation, $year, $month, true);
$defenderList[] = new WarUnitGeneral(
$tmpRNG,
$defenderGeneral,
$rawDefenderNation,
false
);
} }
if ($action == 'reorder') {
$noRng = NoRNG::rngInstance();
$cityCheck = [ usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) {
'required'=>[ return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker));
'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',
],
'numeric'=>[
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
],
'integer'=>[
'city', 'nation', 'supply',
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'state',
],
'min'=>[
['def', 0],
['wall', 0],
['trust', 0],
['pop', 0],
['comm', 0],
['secu', 0],
['city', 1],
['nation', 0]
],
'in'=>[
['level', array_keys(getCityLevelList())]
]
];
$v = new Validator($rawAttackerCity);
$v->rules($cityCheck);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>'[출병도시]'.$v->errorStr()
]);
}
$v = new Validator($rawDefenderCity);
$v->rules($cityCheck);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>'[수비도시]'.$v->errorStr()
]);
}
$nationCheck = [
'required'=>[
'type', 'tech', 'level', 'capital',
'nation', 'name', 'gold', 'rice', 'gennum'
],
'integer'=>[
'level', 'capital', 'nation', 'gennum',
],
'numeric'=>[
'tech', 'gold', 'rice'
],
'min'=>[
['tech', 0],
['gold', 0],
['rice', 0],
['gennum', 1],
],
'in'=>[
['type', GameConst::$availableNationType],
['level', array_keys(getNationLevelList())]
]
];
$v = new Validator($rawAttackerNation);
$v->rules($nationCheck);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>'[출병국]'.$v->errorStr()
]);
}
$v = new Validator($rawDefenderNation);
$v->rules($nationCheck);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>'[수비국]'.$v->errorStr()
]);
}
if($action == 'reorder'){
usort($defenderList, function(General $lhs, General $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
}); });
$order = []; $order = [];
foreach($defenderList as $defenderGeneral){ foreach ($defenderList as $defender) {
$order[] = $defenderGeneral->getID(); $order[] = $defender->getGeneral()->getID();
} }
Json::die([ Json::die([
'result'=>true, 'result' => true,
'reason'=>'success', 'reason' => 'success',
'order'=>$order 'order' => $order
]); ]);
} }
usort($defenderList, function(General $lhs, General $rhs){ $rawDefenderList = [];
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs)); foreach($defenderList as $unit){
}); if(extractBattleOrder($unit, $attacker) <= 0){
continue;
$rawDefenderList = array_map(function(General $general){ }
return $general->getRaw(); $rawDefenderList[] = $unit->getRaw();
}, $defenderList); }
unset($defenderList); unset($defenderList);
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$startYear = $gameStor->startyear; $startYear = $gameStor->startyear;
function extractRankVar(array $rawVal):Map{ function extractRankVar(array $rawVal): Map
{
$rankVars = new Map; $rankVars = new Map;
foreach($rawVal as $rawKey=>$rawVal){ foreach ($rawVal as $rawKey => $rawVal) {
$key = RankColumn::tryFrom($rawKey); $key = RankColumn::tryFrom($rawKey);
if($key === null){ if ($key === null) {
continue; continue;
} }
$rankVars[$key] = $rawVal; $rankVars[$key] = $rawVal;
@@ -336,80 +364,104 @@ function extractRankVar(array $rawVal):Map{
} }
function simulateBattle( function simulateBattle(
$rawAttacker, $rawAttackerCity, $rawAttackerNation, $rawAttacker,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation, $rawAttackerCity,
$startYear, $year, $month, $warSeed $rawAttackerNation,
){ $rawDefenderList,
$rawDefenderCity,
$rawDefenderNation,
$startYear,
$year,
$month,
$warSeed
) {
if(!$warSeed){ if (!$warSeed) {
$warSeed = bin2hex(random_bytes(16)); $warSeed = bin2hex(random_bytes(16));
} }
$warRng = new RandUtil(new LiteHashDRBG($warSeed)); $warRng = new RandUtil(new LiteHashDRBG($warSeed));
$attackerGeneral = new General($rawAttacker, extractRankVar($rawAttacker), null, $rawAttackerCity, $rawAttackerNation, $year, $month);
$attacker = new WarUnitGeneral( $attacker = new WarUnitGeneral(
$warRng, $warRng,
new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month), $attackerGeneral,
$rawAttackerNation, $rawAttackerNation,
true true
); );
$city = new WarUnitCity($warRng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear); $city = new WarUnitCity($warRng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear);
$iterDefender = new \ArrayIterator($rawDefenderList); /** @var WarUnit[] */
$defenderList = [];
foreach ($rawDefenderList as $rawDefenderGeneral) {
$defenderGeneral = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), null, $rawDefenderCity, $rawAttackerNation, $year, $month, true);
$defenderList[] = new WarUnitGeneral(
$warRng,
$defenderGeneral,
$rawDefenderNation,
false
);
}
if(count($defenderList) && extractBattleOrder($city, $attacker) > 0){
$defenderList[] = $city;
}
usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) {
return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker));
});
$iterDefender = new \ArrayIterator($defenderList);
$iterDefender->rewind(); $iterDefender->rewind();
$battleResult = []; $battleResult = [];
$attackerRice = $rawAttacker['rice']; $attackerRice = $attacker->getGeneral()->getVar('rice');
$defenderRice = 0; $defenderRice = 0;
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext) $getNextDefender = function (?WarUnit $prevDefender, bool $reqNext)
use ($warRng, $iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) { use ($iterDefender, &$battleResult, &$defenderRice, $attacker): ?WarUnit {
if($prevDefender !== null){ if ($prevDefender !== null) {
$prevDefender->getLogger()->rollback(); $prevDefender->getLogger()->rollback();
$battleResult[] = $prevDefender; $battleResult[] = $prevDefender;
if($prevDefender instanceof WarUnitGeneral){ if ($prevDefender instanceof WarUnitGeneral) {
$defenderRice -= $prevDefender->getVar('rice'); $defenderRice -= $prevDefender->getVar('rice');
} }
} }
if(!$reqNext){ if (!$reqNext) {
return null; return null;
} }
if(!$iterDefender->valid()){ if (!$iterDefender->valid()) {
return null; return null;
} }
$defenderObj = new General($iterDefender->current(), extractRankVar($iterDefender->current()), $rawDefenderCity, $rawDefenderNation, $year, $month); /** @var WarUnit */
if(extractBattleOrder($defenderObj) <= 0){ $defender = $iterDefender->current();
if (extractBattleOrder($defender, $attacker) <= 0) {
return null; return null;
} }
$defenderRice += $defenderObj->getVar('rice'); if($defender instanceof WarUnitGeneral){
$defenderRice += $defender->getVar('rice');
}
$retVal = new WarUnitGeneral(
$warRng,
$defenderObj,
$rawDefenderNation,
false
);
$iterDefender->next(); $iterDefender->next();
return $retVal; return $defender;
}; };
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear); $conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city);
$rawDefenderCity = $city->getRaw();
$updateAttackerNation = [];
$updateDefenderNation = [];
$attackerRice -= $attacker->getVar('rice'); $attackerRice -= $attacker->getVar('rice');
if($city->getPhase() > 0){ if ($city->getPhase() > 0) {
$rice = $city->getKilled() / 100 * 0.8; $rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice; $rice *= $city->getCrewType()->rice;
$rice *= getTechCost($rawDefenderNation['tech']); $rice *= getTechCost($city->getRawNation()['tech']);
$rice *= $city->getCityTrainAtmos() / 100 - 0.2; $rice *= $city->getCityTrainAtmos() / 100 - 0.2;
Util::setRound($rice); Util::setRound($rice);
@@ -417,8 +469,8 @@ function simulateBattle(
} }
$totalDead = $attacker->getKilled() + $attacker->getDead(); $totalDead = $attacker->getKilled() + $attacker->getDead();
$attackerCityDead = $totalDead * 0.4; //$attackerCityDead = $totalDead * 0.4;
$defenderCityDead = $totalDead * 0.6; //$defenderCityDead = $totalDead * 0.6;
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice]; return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
} }
@@ -444,18 +496,26 @@ $avgWar = 0;
$attackerActivatedSkills = []; $attackerActivatedSkills = [];
$defendersActivatedSkills = []; $defendersActivatedSkills = [];
if($warSeed){
$repeatCnt = 1;
}
foreach(Util::range($repeatCnt) as $repeatIdx){ foreach (Util::range($repeatCnt) as $repeatIdx) {
if($repeatIdx > 0){
$warSeed = bin2hex(random_bytes(16));
}
/** @var WarUnit $attacker */ /** @var WarUnit $attacker */
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle( [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
$rawAttacker, $rawAttackerCity, $rawAttackerNation, $rawAttacker,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation, $rawAttackerCity,
$startYear, $year, $month, $warSeed $rawAttackerNation,
$rawDefenderList,
$rawDefenderCity,
$rawDefenderNation,
$startYear,
$year,
$month,
$warSeed
); );
$lastWarLog = Util::mapWithKey(function($key, $values){ $lastWarLog = Util::mapWithKey(function ($key, $values) {
return ConvertLog(join('<br>', $values)); return ConvertLog(join('<br>', $values));
}, $attacker->getLogger()->rollback()); }, $attacker->getLogger()->rollback());
@@ -478,48 +538,45 @@ foreach(Util::range($repeatCnt) as $repeatIdx){
$avgWar += count($battleResult) / $repeatCnt; $avgWar += count($battleResult) / $repeatCnt;
foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){ foreach ($attacker->getActivatedSkillLog() as $skillName => $skillCnt) {
if(!key_exists($skillName, $attackerActivatedSkills)){ if (!key_exists($skillName, $attackerActivatedSkills)) {
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt; $attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
} } else {
else{
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt; $attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
} }
} }
foreach($battleResult as $idx=>$defender){ foreach ($battleResult as $idx => $defender) {
while($idx >= count($defendersActivatedSkills)){ while ($idx >= count($defendersActivatedSkills)) {
$defendersActivatedSkills[] = []; $defendersActivatedSkills[] = [];
} }
$activatedSkills = &$defendersActivatedSkills[$idx]; $activatedSkills = &$defendersActivatedSkills[$idx];
foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){ foreach ($defender->getActivatedSkillLog() as $skillName => $skillCnt) {
if(!key_exists($skillName, $activatedSkills)){ if (!key_exists($skillName, $activatedSkills)) {
$activatedSkills[$skillName] = $skillCnt / $repeatCnt; $activatedSkills[$skillName] = $skillCnt / $repeatCnt;
} } else {
else{
$activatedSkills[$skillName] += $skillCnt / $repeatCnt; $activatedSkills[$skillName] += $skillCnt / $repeatCnt;
} }
} }
} }
} }
Json::die([ Json::die([
'result'=>true, 'result' => true,
'datetime'=>$rawAttacker['turntime'], 'datetime' => $rawAttacker['turntime'],
'reason'=>'success', 'reason' => 'success',
'lastWarLog'=>$lastWarLog, 'lastWarLog' => $lastWarLog,
'avgWar'=>$avgWar, 'avgWar' => $avgWar,
'phase'=>$avgPhase, 'phase' => $avgPhase,
'killed'=>$attackerKilled, 'killed' => $attackerKilled,
'maxKilled'=>$attackerMaxKilled, 'maxKilled' => $attackerMaxKilled,
'minKilled'=>$attackerMinKilled, 'minKilled' => $attackerMinKilled,
'dead'=>$attackerDead, 'dead' => $attackerDead,
'maxDead'=>$attackerMaxDead, 'maxDead' => $attackerMaxDead,
'minDead'=>$attackerMinDead, 'minDead' => $attackerMinDead,
'attackerRice'=>$attackerAvgRice, 'attackerRice' => $attackerAvgRice,
'defenderRice'=>$defenderAvgRice, 'defenderRice' => $defenderAvgRice,
'attackerSkills'=>$attackerActivatedSkills, 'attackerSkills' => $attackerActivatedSkills,
'defendersSkills'=>$defendersActivatedSkills, 'defendersSkills' => $defendersActivatedSkills,
]); ]);
+30 -28
View File
@@ -3,6 +3,7 @@
namespace sammo; namespace sammo;
use sammo\DTO\VoteInfo; use sammo\DTO\VoteInfo;
use sammo\Enums\GeneralQueryMode;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
@@ -29,7 +30,8 @@ if (!$session->isGameLoggedIn()) {
} }
$me = $db->queryFirstRow( $me = $db->queryFirstRow(
'SELECT no,con,turntime,newmsg,newvote,`officer_level` from general where owner = %i', 'SELECT no,refresh_score,turntime,newmsg,newvote,`officer_level` FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner = %i',
$userID $userID
); );
@@ -51,13 +53,13 @@ if ($me['newmsg'] == 1 || $me['newvote'] == 1) {
$plock = boolval($db->queryFirstField('SELECT plock FROM plock WHERE `type`="GAME" LIMIT 1')); $plock = boolval($db->queryFirstField('SELECT plock FROM plock WHERE `type`="GAME" LIMIT 1'));
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
$generalObj = General::createGeneralObjFromDB($me['no']); $generalObj = General::createGeneralObjFromDB($me['no'], null, GeneralQueryMode::FullWithAccessLog);
$generalObj->setRawCity($db->queryFirstRow('SELECT * FROM city WHERE city = %i', $generalObj->getCityID())); $generalObj->setRawCity($db->queryFirstRow('SELECT * FROM city WHERE city = %i', $generalObj->getCityID()));
$scenario = $gameStor->scenario_text; $scenario = $gameStor->scenario_text;
@@ -180,44 +182,44 @@ if ($lastVoteID) {
</div> </div>
<div class="row center gx-0"> <div class="row center gx-0">
<div class="s-border-t col py-2 col-8 col-md-4" style="color:<?= $color ?>;"> <div class="s-border-t col py-2 col-8 col-lg-4" style="color:<?= $color ?>;">
<?= $scenario ?> <?= $scenario ?>
</div> </div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;"> <div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
NPC 수, 상성 : <?= $extend ?>,<?= $fiction ?> NPC 수, 상성 : <?= $extend ?>,<?= $fiction ?>
</div> </div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;"> <div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
NPC선택 : <?= $npcmode ?> NPC선택 : <?= $npcmode ?>
</div> </div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;"> <div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
토너먼트 : <?= getTournamentTermText($gameStor->turnterm) ?> 토너먼트 : <?= getTournamentTermText($gameStor->turnterm) ?>
</div> </div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;"> <div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
기타 설정: <?= $otherTextInfo ?> 기타 설정: <?= $otherTextInfo ?>
</div> </div>
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(2) ?></div> <div class="s-border-t col py-2 col-8 col-lg-4"><?= info(2) ?></div>
<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-lg-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-4 col-lg-2">턴당 갱신횟수 : <?= $gameStor->refreshLimit ?>회</div>
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(3) ?></div> <div class="s-border-t col py-2 col-8 col-lg-4"><?= info(3) ?></div>
<div class="s-border-t py-2 col col-6 col-md-4"> <div class="s-border-t py-2 col col-6 col-lg-4">
<?php if ($isTournamentActive) : ?> <?php if ($isTournamentActive) : ?>
↑<span style='color:cyan'><?= (['전력전', '통솔전', '일기토', '설전',])[$gameStor->tnmt_type] ?? '' ?> <?= getTournament($gameStor->tournament) ?> <?= getTournamentTime() ?></span>↑ ↑<span style='color:cyan'><?= (['전력전', '통솔전', '일기토', '설전',])[$gameStor->tnmt_type] ?? '' ?> <?= getTournament($gameStor->tournament) ?> <?= getTournamentTime() ?></span>↑
<?php else : ?> <?php else : ?>
<span style='color:magenta'>현재 토너먼트 경기 없음</span> <span style='color:magenta'>현재 토너먼트 경기 없음</span>
<?php endif; ?> <?php endif; ?>
</div> </div>
<div class="s-border-t py-2 col col-6 col-md-2"> <div class="s-border-t py-2 col col-6 col-lg-2">
<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 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>
<div class="s-border-t py-2 col col-6 col-md-2"> <div class="s-border-t py-2 col col-6 col-lg-2">
<?php if ($auctionCount > 0) : ?> <?php if ($auctionCount > 0) : ?>
<span style='color:cyan'><?= $auctionCount ?>건</span> 거래 진행중 <span style='color:cyan'><?= $auctionCount ?>건</span> 거래 진행중
<?php else : ?> <?php else : ?>
<span style='color:magenta'>진행중 거래 없음</span> <span style='color:magenta'>진행중 거래 없음</span>
<?php endif; ?> <?php endif; ?>
</div> </div>
<div class="s-border-t py-2 col col-6 col-md-4 vote-cell"> <div class="s-border-t py-2 col col-6 col-lg-4 vote-cell">
<?php <?php
?> ?>
<?php if ($lastVote === null) : ?> <?php if ($lastVote === null) : ?>
@@ -310,11 +312,11 @@ if ($lastVoteID) {
</div> </div>
</div> </div>
<div class="row gx-0"> <div class="row gx-0">
<div class="col-md-6" id="general_public_record-position"> <div class="col-lg-6" id="general_public_record-position">
<div class="bg1 center s-border-tb"><b>장수 동향</b></div> <div class="bg1 center s-border-tb"><b>장수 동향</b></div>
<div id="general_public_record" style="text-align:left;"><?= formatHistoryToHTML(getGlobalActionLogRecent(15)) ?></div> <div id="general_public_record" style="text-align:left;"><?= formatHistoryToHTML(getGlobalActionLogRecent(15)) ?></div>
</div> </div>
<div class="col-md-6" id="general_log-position"> <div class="col-lg-6" id="general_log-position">
<div class="bg1 center s-border-tb"><b>개인 기록</b></div> <div class="bg1 center s-border-tb"><b>개인 기록</b></div>
<div id="general_log" style="text-align:left;"><?= formatHistoryToHTML(getGeneralActionLogRecent($me['no'], 15)) ?></div> <div id="general_log" style="text-align:left;"><?= formatHistoryToHTML(getGeneralActionLogRecent($me['no'], 15)) ?></div>
</div> </div>
@@ -328,34 +330,34 @@ if ($lastVoteID) {
<div id="message_board" class="row gx-0"> <div id="message_board" class="row gx-0">
<div class="message_input_form bg0 gx-0 row"> <div class="message_input_form bg0 gx-0 row">
<div id="mailbox_list-col" class="col-6 col-md-2 d-grid"> <div id="mailbox_list-col" class="col-6 col-lg-2 d-grid">
<select id="mailbox_list" size="1" class="form-control bg-dark text-white"> <select id="mailbox_list" size="1" class="form-control bg-dark text-white">
</select> </select>
</div> </div>
<div id="msg_input-col" class="col-12 col-md-8 d-grid"> <div id="msg_input-col" class="col-12 col-lg-8 d-grid">
<input type="text" id="msg_input" maxlength="99" class="form-control"> <input type="text" id="msg_input" maxlength="99" class="form-control">
</div> </div>
<div id="msg_submit-col" class="col-6 col-md-2 d-grid"><button id="msg_submit" class="btn btn-primary">서신전달&amp;갱신</button></div> <div id="msg_submit-col" class="col-6 col-lg-2 d-grid"><button id="msg_submit" class="btn btn-primary">서신전달&amp;갱신</button></div>
</div> </div>
<div class="col-md-6 board_side bg0"><a id="public_talk_position"></a> <div class="col-lg-6 board_side bg0"><a id="public_talk_position"></a>
<div class="board_header bg0">전체 메시지(최고99자)</div> <div class="board_header bg0">전체 메시지(최고99자)</div>
<section class="public_message"> <section class="public_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="public">이전 메시지 불러오기</button></div> <div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="public">이전 메시지 불러오기</button></div>
</section> </section>
</div> </div>
<div class="col-md-6 board_side bg0"><a id="national_talk_position"></a> <div class="col-lg-6 board_side bg0"><a id="national_talk_position"></a>
<div class="board_header bg0">국가 메시지(최고99자)</div> <div class="board_header bg0">국가 메시지(최고99자)</div>
<section class="national_message"> <section class="national_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="national">이전 메시지 불러오기</button></div> <div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="national">이전 메시지 불러오기</button></div>
</section> </section>
</div> </div>
<div class="col-md-6 board_side bg0"><a id="private_talk_position"></a> <div class="col-lg-6 board_side bg0"><a id="private_talk_position"></a>
<div class="board_header bg0">개인 메시지(최고99자)</div> <div class="board_header bg0">개인 메시지(최고99자)</div>
<section class="private_message"> <section class="private_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="private">이전 메시지 불러오기</button></div> <div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="private">이전 메시지 불러오기</button></div>
</section> </section>
</div> </div>
<div class="col-md-6 board_side bg0"><a id="diplomacy_talk_position"></a> <div class="col-lg-6 board_side bg0"><a id="diplomacy_talk_position"></a>
<div class="board_header bg0">외교 메시지(최고99자)</div> <div class="board_header bg0">외교 메시지(최고99자)</div>
<section class="diplomacy_message"> <section class="diplomacy_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="diplomacy">이전 메시지 불러오기</button></div> <div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="diplomacy">이전 메시지 불러오기</button></div>
@@ -367,7 +369,7 @@ if ($lastVoteID) {
</div> </div>
</div> </div>
<?php <?php
if ($con == 1) { if ($limitState == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!"); MessageBox("접속제한이 얼마 남지 않았습니다!");
} }
if ($me['newmsg'] == 1) { if ($me['newmsg'] == 1) {
@@ -379,7 +381,7 @@ if ($lastVoteID) {
} }
?> ?>
</div> </div>
<nav class="navbar navbar-expand fixed-bottom navbar-dark bg-dark d-sm-block d-md-none p-0" id="navbar500"> <nav class="navbar navbar-expand fixed-bottom navbar-dark bg-dark d-sm-block d-lg-none p-0" id="navbar500">
<div class="container-fluid px-0"> <div class="container-fluid px-0">
<div class="collapse navbar-collapse"> <div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mx-auto"> <ul class="navbar-nav me-auto mx-auto">
+67 -34
View File
@@ -3,6 +3,7 @@
namespace sammo; namespace sammo;
use sammo\Enums\EventTarget; use sammo\Enums\EventTarget;
use sammo\Enums\GeneralQueryMode;
function processWar(string $warSeed, General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity) function processWar(string $warSeed, General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity)
{ {
@@ -37,16 +38,32 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
$city = new WarUnitCity($rng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear); $city = new WarUnitCity($rng, $rawDefenderCity, $rawDefenderNation, $year, $month, $startYear);
$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')); $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); $defenderGeneralList = General::createGeneralObjListFromDB($defenderIDList, null);
usort($defenderList, function (General $lhs, General $rhs) { /** @var WarUnit[] */
return - (extractBattleOrder($lhs) <=> extractBattleOrder($rhs)); $defenderList = [];
foreach($defenderGeneralList as $defenderGeneral){
$defenderGeneral->setRawCity($rawDefenderCity);
$defenderCandidate = new WarUnitGeneral($rng, $defenderGeneral, $rawDefenderNation, false);
if(extractBattleOrder($defenderCandidate, $attacker) <= 0){
continue;
}
$defenderList[] = $defenderCandidate;
}
if(count($defenderList) && extractBattleOrder($city, $attacker) > 0){
$defenderList[] = $city;
}
usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) {
return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker));
}); });
$iterDefender = new \ArrayIterator($defenderList); $iterDefender = new \ArrayIterator($defenderList);
$iterDefender->rewind(); $iterDefender->rewind();
$getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($rng, $iterDefender, $rawDefenderNation, $rawDefenderCity, $db) { $getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $db, $attacker) {
if ($prevDefender !== null) { if ($prevDefender !== null) {
$prevDefender->applyDB($db); $prevDefender->applyDB($db);
} }
@@ -59,24 +76,16 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
return null; return null;
} }
/** @var WarUnit */
$nextDefender = $iterDefender->current(); $nextDefender = $iterDefender->current();
$nextDefender->setRawCity($rawDefenderCity); if (extractBattleOrder($nextDefender, $attacker) <= 0) {
if (extractBattleOrder($nextDefender) <= 0) {
return null; return null;
} }
$retVal = new WarUnitGeneral(
$rng,
$nextDefender,
$rawDefenderNation,
false
);
$iterDefender->next(); $iterDefender->next();
return $retVal; return $nextDefender;
}; };
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear); $conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city);
$attacker->applyDB($db); $attacker->applyDB($db);
@@ -180,8 +189,17 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
], $attacker->getGeneral(), $city->getRaw()); ], $attacker->getGeneral(), $city->getRaw());
} }
function extractBattleOrder(General $general) function extractBattleOrder(WarUnit $defender, WarUnit $attacker)
{ {
if($defender instanceof WarUnitCity){
if(!($attacker instanceof WarUnitGeneral)){
return 0;
}
$attackerGeneral = $attacker->getGeneral();
return $attackerGeneral->onCalcOpposeStat($defender->getGeneral(), 'cityBattleOrder', -1);
}
$general = $defender->getGeneral();
if ($general->getVar('crew') == 0) { if ($general->getVar('crew') == 0) {
return 0; return 0;
} }
@@ -212,7 +230,6 @@ function processWar_NG(
WarUnitGeneral $attacker, WarUnitGeneral $attacker,
callable $getNextDefender, callable $getNextDefender,
WarUnitCity $city, WarUnitCity $city,
int $relYear
): bool { ): bool {
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
@@ -225,6 +242,7 @@ function processWar_NG(
$attackerNationUpdate = []; $attackerNationUpdate = [];
$defenderNationUpdate = []; $defenderNationUpdate = [];
/** @var WarUnit */
$defender = ($getNextDefender)(null, true); $defender = ($getNextDefender)(null, true);
$conquerCity = false; $conquerCity = false;
@@ -240,6 +258,7 @@ function processWar_NG(
$logWritten = false; $logWritten = false;
if ($defender === null) { if ($defender === null) {
$defender = $city; $defender = $city;
$defender->setSiege();
if ($city->getNationVar('rice') <= 0 && $city->getVar('supply')) { if ($city->getNationVar('rice') <= 0 && $city->getVar('supply')) {
//병량 패퇴 //병량 패퇴
@@ -406,21 +425,28 @@ function processWar_NG(
$attacker->logBattleResult(); $attacker->logBattleResult();
$defender->logBattleResult(); $defender->logBattleResult();
$attacker->addWin(); if (!($defender instanceof WarUnitCity) || $defender->isSiege()){
$defender->addLose(); $attacker->addWin();
$defender->addLose();
$attacker->tryWound(); $attacker->tryWound();
$defender->tryWound(); $defender->tryWound();
if ($defender === $city) { if ($defender === $city) {
$attacker->addLevelExp(1000); $attacker->addLevelExp(1000);
$conquerCity = true; $conquerCity = true;
break; break;
}
} }
$josaYi = JosaUtil::pick($defender->getCrewTypeName(), '이'); $josaYi = JosaUtil::pick($defender->getCrewTypeName(), '이');
if ($noRice) { if ($defender instanceof WarUnitCity && !$defender->isSiege()){
//실제 공성을 위해 다시 초기화
$defender->setOppose(null);
}
else if ($noRice) {
$logger->pushGlobalActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다."); $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); $defender->getLogger()->pushGeneralActionLog("군량 부족으로 패퇴합니다.", ActionLogger::PLAIN);
@@ -455,12 +481,18 @@ function processWar_NG(
$attacker->finishBattle(); $attacker->finishBattle();
$defender->finishBattle(); $defender->finishBattle();
if ($defender instanceof WarUnitCity) { if($city->getDead() || $defender instanceof WarUnitCity){
$newConflict = $defender->addConflict(); if($city !== $defender){
$city->setOppose($attacker);
$city->setSiege();
$city->finishBattle();
}
$newConflict = $city->addConflict();
if ($newConflict) { if ($newConflict) {
$nationName = $attacker->getNationVar('name'); $nationName = $attacker->getNationVar('name');
$josaYi = JosaUtil::pick($nationName, '이'); $josaYi = JosaUtil::pick($nationName, '이');
$logger->pushGlobalHistoryLog("<M><b>【분쟁】</b></><D><b>{$nationName}</b></>{$josaYi} <G><b>{$defender->getName()}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다."); $logger->pushGlobalHistoryLog("<M><b>【분쟁】</b></><D><b>{$nationName}</b></>{$josaYi} <G><b>{$city->getName()}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다.");
} }
} }
@@ -564,10 +596,10 @@ function ConquerCity(array $admin, General $general, array $city)
$lord = new General($db->queryFirstRow( $lord = new General($db->queryFirstRow(
'SELECT %l FROM general WHERE nation = %i AND officer_level = %i LIMIT 1', 'SELECT %l FROM general WHERE nation = %i AND officer_level = %i LIMIT 1',
Util::formatListOfBackticks(General::mergeQueryColumn(['npc', 'gold', 'rice', 'experience', 'explevel', 'belong', 'dedication', 'dedlevel', 'aux'], 1)[0]), Util::formatListOfBackticks(General::mergeQueryColumn(['npc', 'gold', 'rice', 'experience', 'explevel', 'belong', 'dedication', 'dedlevel', 'aux'], GeneralQueryMode::Lite)[0]),
$defenderNationID, $defenderNationID,
12 12
), null, $city, $loseNation, $year, $month, false); ), null, null, $city, $loseNation, $year, $month, false);
$josaUl = JosaUtil::pick($defenderNationName, '을'); $josaUl = JosaUtil::pick($defenderNationName, '을');
$attackerLogger->pushNationalHistoryLog("<D><b>{$defenderNationName}</b></>{$josaUl} 정복"); $attackerLogger->pushNationalHistoryLog("<D><b>{$defenderNationName}</b></>{$josaUl} 정복");
@@ -664,11 +696,12 @@ function ConquerCity(array $admin, General $general, array $city)
$minCity = findNextCapital($cityID, $defenderNationID); $minCity = findNextCapital($cityID, $defenderNationID);
$minCityName = CityConst::byID($minCity)->name; $minCityName = CityConst::byID($minCity)->name;
$josaRo = JosaUtil::pick($minCityName, '로');
$josaYi = JosaUtil::pick($defenderNationName, '이'); $josaYi = JosaUtil::pick($defenderNationName, '이');
$attackerLogger->pushGlobalHistoryLog("<M><b>【긴급천도】</b></><D><b>{$defenderNationName}</b></>{$josaYi} 수도가 함락되어 <G><b>$minCityName</b></>으로 긴급천도하였습니다."); $attackerLogger->pushGlobalHistoryLog("<M><b>【긴급천도】</b></><D><b>{$defenderNationName}</b></>{$josaYi} 수도가 함락되어 <G><b>$minCityName</b></>{$josaRo} 긴급천도하였습니다.");
$moveLog = "수도가 함락되어 <G><b>$minCityName</b></>으로 <M>긴급천도</>합니다."; $moveLog = "수도가 함락되어 <G><b>$minCityName</b></>{$josaRo} <M>긴급천도</>합니다.";
//아국 수뇌부에게 로그 전달 //아국 수뇌부에게 로그 전달
foreach ($db->queryFirstColumn( foreach ($db->queryFirstColumn(
'SELECT no FROM general WHERE nation=%i AND officer_level>=5', 'SELECT no FROM general WHERE nation=%i AND officer_level>=5',
@@ -10,6 +10,7 @@ use sammo\DTO\AuctionBidItem;
use sammo\DTO\AuctionInfo; use sammo\DTO\AuctionInfo;
use sammo\Enums\APIRecoveryType; use sammo\Enums\APIRecoveryType;
use sammo\Enums\AuctionType; use sammo\Enums\AuctionType;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\InheritanceKey; use sammo\Enums\InheritanceKey;
use sammo\InheritancePointManager; use sammo\InheritancePointManager;
use sammo\TimeUtil; use sammo\TimeUtil;
@@ -76,7 +77,7 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI
$inheritMgr = InheritancePointManager::getInstance(); $inheritMgr = InheritancePointManager::getInstance();
//preveious라서 column을 최대한 비울 수 있다. //preveious라서 column을 최대한 비울 수 있다.
$remainPoint = $inheritMgr->getInheritancePoint( $remainPoint = $inheritMgr->getInheritancePoint(
General::createGeneralObjFromDB($generalID, ['owner'], 0), General::createGeneralObjFromDB($generalID, ['owner'], GeneralQueryMode::Core),
InheritanceKey::previous InheritanceKey::previous
); );
+6 -3
View File
@@ -42,9 +42,12 @@ class GetBettingList extends \sammo\BaseAPI
$bettingStor = KVStorage::getStorage($db, 'betting'); $bettingStor = KVStorage::getStorage($db, 'betting');
$userID = $session->userID; $userID = $session->userID;
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,penalty,permission FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
$con = checkLimit($me['con']); 'SELECT no,nation,officer_level,refresh_score,turntime,belong,penalty,permission FROM `general`
if ($con >= 2) { LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
return "접속 제한중입니다."; return "접속 제한중입니다.";
} }
@@ -39,7 +39,7 @@ class BuildNationCandidate extends \sammo\BaseAPI
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['opentime', 'turntime']); $gameStor->cacheValues(['opentime', 'turntime']);
$general = $db->queryFirstRow('SELECT no,name,nation,owner_name,npc,lastrefresh FROM general WHERE owner=%i', $userID); $general = $db->queryFirstRow('SELECT no,name,nation,owner_name,npc FROM general WHERE owner=%i', $userID);
if (!$general) { if (!$general) {
return '장수가 없습니다'; return '장수가 없습니다';
+9 -2
View File
@@ -5,6 +5,7 @@ namespace sammo\API\General;
use sammo\DB; use sammo\DB;
use sammo\DummyGeneral; use sammo\DummyGeneral;
use sammo\Enums\APIRecoveryType; use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralAccessLogColumn;
use sammo\GameConst; use sammo\GameConst;
use sammo\Session; use sammo\Session;
use sammo\General; use sammo\General;
@@ -37,7 +38,13 @@ class DieOnPrestart extends \sammo\BaseAPI
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['turnterm', 'opentime', 'turntime', 'year', 'month']); $gameStor->cacheValues(['turnterm', 'opentime', 'turntime', 'year', 'month']);
$general = $db->queryFirstRow('SELECT no,name,nation,owner_name,npc,lastrefresh FROM general WHERE owner=%i AND npc = 0', $userID); $general = $db->queryFirstRow('SELECT no,name,nation,owner_name,npc FROM general WHERE owner=%i AND npc = 0', $userID);
$lastRefresh = $db->queryFirstField(
'SELECT %b FROM general_access_log WHERE %b = %i',
GeneralAccessLogColumn::lastRefresh->value,
GeneralAccessLogColumn::generalID->value,
$general['no']
);
if (!$general) { if (!$general) {
return '장수가 없습니다'; return '장수가 없습니다';
@@ -55,7 +62,7 @@ class DieOnPrestart extends \sammo\BaseAPI
} }
//서버 가오픈시 할 수 있는 행동 //서버 가오픈시 할 수 있는 행동
$targetTime = addTurn($general['lastrefresh'], $gameStor->turnterm, GameConst::$minTurnDieOnPrestart); $targetTime = addTurn($lastRefresh, $gameStor->turnterm, GameConst::$minTurnDieOnPrestart);
if ($targetTime > TimeUtil::now()) { if ($targetTime > TimeUtil::now()) {
$targetTimeShort = substr($targetTime, 0, 19); $targetTimeShort = substr($targetTime, 0, 19);
return "아직 삭제할 수 없습니다. {$targetTimeShort} 부터 가능합니다."; return "아직 삭제할 수 없습니다. {$targetTimeShort} 부터 가능합니다.";
+18 -6
View File
@@ -9,7 +9,9 @@ use sammo\DB;
use sammo\DTO\VoteInfo; use sammo\DTO\VoteInfo;
use sammo\Enums\APIRecoveryType; use sammo\Enums\APIRecoveryType;
use sammo\Enums\CityColumn; use sammo\Enums\CityColumn;
use sammo\Enums\GeneralAccessLogColumn;
use sammo\Enums\GeneralColumn; use sammo\Enums\GeneralColumn;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\RankColumn; use sammo\Enums\RankColumn;
use sammo\GameConst; use sammo\GameConst;
use sammo\General; use sammo\General;
@@ -173,7 +175,7 @@ class GetFrontInfo extends \sammo\BaseAPI
'online_nation', 'online_user_cnt', 'online_nation', 'online_user_cnt',
'year', 'month', 'startyear', 'year', 'month', 'startyear',
'maxgeneral', 'maxgeneral',
'conlimit', 'refreshLimit',
'server_cnt', 'server_cnt',
]); ]);
@@ -383,7 +385,8 @@ class GetFrontInfo extends \sammo\BaseAPI
'specialWar' => $general->getVar(GeneralColumn::special2), // GameObjClassKey; 'specialWar' => $general->getVar(GeneralColumn::special2), // GameObjClassKey;
'personal' => $general->getVar(GeneralColumn::personal), // GameObjClassKey; 'personal' => $general->getVar(GeneralColumn::personal), // GameObjClassKey;
'belong' => $general->getVar(GeneralColumn::belong), // number; 'belong' => $general->getVar(GeneralColumn::belong), // number;
'connect' => $general->getVar(GeneralColumn::connect), // number;
'refreshScoreTotal' => $general->getAccessLogVar(GeneralAccessLogColumn::refreshScoreTotal, 0), // number;
'officerLevel' => $general->getVar(GeneralColumn::officer_level), // number; 'officerLevel' => $general->getVar(GeneralColumn::officer_level), // number;
'officerLevelText' => getOfficerLevelText($general->getVar(GeneralColumn::officer_level), $rawNation['level']), // string; 'officerLevelText' => getOfficerLevelText($general->getVar(GeneralColumn::officer_level), $rawNation['level']), // string;
@@ -400,7 +403,7 @@ class GetFrontInfo extends \sammo\BaseAPI
'troop' => $general->getVar(GeneralColumn::troop), // number; 'troop' => $general->getVar(GeneralColumn::troop), // number;
//P0 End //P0 End
'con' => $general->getVar(GeneralColumn::con), // number; 'refreshScore' => $general->getAccessLogVar(GeneralAccessLogColumn::refreshScore, 0), // number;
'specage' => $general->getVar(GeneralColumn::specage), // number; 'specage' => $general->getVar(GeneralColumn::specage), // number;
'specage2' => $general->getVar(GeneralColumn::specage2), // number; 'specage2' => $general->getVar(GeneralColumn::specage2), // number;
'leadership_exp' => $general->getVar(GeneralColumn::leadership_exp), // number; 'leadership_exp' => $general->getVar(GeneralColumn::leadership_exp), // number;
@@ -531,12 +534,12 @@ class GetFrontInfo extends \sammo\BaseAPI
{ {
$generalID = $session->generalID; $generalID = $session->generalID;
//NOTE: 이 경우 staticNation 정보를 조회한다. //NOTE: 이 경우 staticNation 정보를 조회한다.
$general = General::createGeneralObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID, null, GeneralQueryMode::FullWithAccessLog);
$nationID = $general->getNationID(); $nationID = $general->getNationID();
$cityID = $general->getCityID(); $cityID = $general->getCityID();
$con = checkLimit($general->getVar('con')); $limitState = checkLimit($general->getAccessLogVar(GeneralAccessLogColumn::refreshScore, 0));
if ($con >= 2) { if ($limitState >= 2) {
return [ return [
'result' => false, 'result' => false,
'reason' => '접속 제한중입니다.', 'reason' => '접속 제한중입니다.',
@@ -569,6 +572,14 @@ class GetFrontInfo extends \sammo\BaseAPI
//TODO: 마지막 투표, 토너먼트, 베팅을 했는지 정보를 별도로 가져와야 함. aux? //TODO: 마지막 투표, 토너먼트, 베팅을 했는지 정보를 별도로 가져와야 함. aux?
$auxInfo = [];
if ($globalInfo['lastVote']) {
$myLastVoteID = $db->queryFirstField('SELECT vote_id FROM vote WHERE general_id = %i ORDER BY vote_id DESC LIMIT 1', $generalID);
if($myLastVoteID) {
$auxInfo['myLastVote'] = $myLastVoteID;
}
}
return [ return [
'result' => true, 'result' => true,
@@ -577,6 +588,7 @@ class GetFrontInfo extends \sammo\BaseAPI
'nation' => $nationInfo, 'nation' => $nationInfo,
'general' => $generalInfo, 'general' => $generalInfo,
'city' => $cityInfo, 'city' => $cityInfo,
'aux' => $auxInfo,
]; ];
} }
} }
+6 -2
View File
@@ -8,6 +8,7 @@ use sammo\Auction;
use sammo\CityConst; use sammo\CityConst;
use sammo\DB; use sammo\DB;
use sammo\Enums\APIRecoveryType; use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralAccessLogColumn;
use sammo\Enums\RankColumn; use sammo\Enums\RankColumn;
use sammo\GameConst; use sammo\GameConst;
use sammo\GameUnitConst; use sammo\GameUnitConst;
@@ -414,8 +415,6 @@ class Join extends \sammo\BaseAPI
'officer_level' => 0, 'officer_level' => 0,
'turntime' => $turntime, 'turntime' => $turntime,
'killturn' => 6, 'killturn' => 6,
'lastconnect' => $now,
'lastrefresh' => $now,
'crewtype' => GameUnitConst::DEFAULT_CREWTYPE, 'crewtype' => GameUnitConst::DEFAULT_CREWTYPE,
'makelimit' => 0, 'makelimit' => 0,
'betray' => $betray, 'betray' => $betray,
@@ -428,6 +427,11 @@ class Join extends \sammo\BaseAPI
'special2' => $special2 'special2' => $special2
]); ]);
$generalID = $db->insertId(); $generalID = $db->insertId();
$db->insert('general_access_log', [
GeneralAccessLogColumn::generalID->value => $generalID,
GeneralAccessLogColumn::userID->value => $userID,
GeneralAccessLogColumn::lastRefresh->value => $now,
]);
if($blockCustomGeneralName){ if($blockCustomGeneralName){
//XXX: 클래스가 이게 맞나? //XXX: 클래스가 이게 맞나?
+12 -6
View File
@@ -42,9 +42,12 @@ class GeneralList extends \sammo\BaseAPI
$userID = $session->userID; $userID = $session->userID;
if ($session->isGameLoggedIn()) { if ($session->isGameLoggedIn()) {
increaseRefresh("장수일람", 2); increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
$con = checkLimit($me['con']); 'SELECT refresh_score, turntime FROM `general`
if ($con >= 2) { LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'; return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.';
} }
} else { } else {
@@ -62,7 +65,8 @@ class GeneralList extends \sammo\BaseAPI
$session->setReadOnly(); $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'); $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,refresh_score_total from `general` LEFT JOIN `general_access_log` ON general.no = general_access_log.general_id');
$ownerNameList = []; $ownerNameList = [];
if ($gameStor->isunited) { if ($gameStor->isunited) {
@@ -73,7 +77,7 @@ class GeneralList extends \sammo\BaseAPI
$generalList = []; $generalList = [];
foreach ($rawGeneralList as $rawGeneral) { 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; [$owner, $no, $picture, $imgsvr, $npc, $age, $nation, $special, $special2, $personal, $name, $ownerName, $injury, $leadership, $strength, $intel, $experience, $dedication, $officerLevel, $killturn, $refreshScoreTotal] = $rawGeneral;
if (key_exists($owner, $ownerNameList)) { if (key_exists($owner, $ownerNameList)) {
$ownerName = $ownerNameList[$owner]; $ownerName = $ownerNameList[$owner];
@@ -104,7 +108,7 @@ class GeneralList extends \sammo\BaseAPI
getDed($dedication), getDed($dedication),
getOfficerLevelText($officerLevel, $nationArr['level']), getOfficerLevelText($officerLevel, $nationArr['level']),
$killturn, $killturn,
$connectCnt $refreshScoreTotal ?: 0,
]; ];
} }
@@ -129,6 +133,8 @@ class GeneralList extends \sammo\BaseAPI
'honorText', 'honorText',
'dedLevelText', 'dedLevelText',
'officerLevelText', 'officerLevelText',
'killturn',
'refreshScoreTotal',
]; ];
$result = [ $result = [
+2 -2
View File
@@ -86,10 +86,10 @@ class GetConst extends \sammo\BaseAPI
if ($lastModified !== null) { if ($lastModified !== null) {
$versionHash = "lt{$lastModified}"; $versionHash = "lt{$lastModified}";
} else { } else {
$versionHash = VersionGit::getHash(); $versionHash = VersionGit::getVersion();
} }
} else { } else {
$versionHash = VersionGit::getHash(); $versionHash = VersionGit::getVersion();
} }
$apiVersion = static::CONST_API_VERSION; $apiVersion = static::CONST_API_VERSION;
+6 -3
View File
@@ -148,13 +148,16 @@ class GetHistory extends \sammo\BaseAPI
} }
increaseRefresh("연감", 1); increaseRefresh("연감", 1);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner = %i', $session->userID); $me = $db->queryFirstRow(
'SELECT refresh_score, turntime FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner = %i', $session->userID
);
if (!$me) { if (!$me) {
return '장수가 사망했습니다.'; return '장수가 사망했습니다.';
} }
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
return templateLimitMsg($me['turntime']); return templateLimitMsg($me['turntime']);
} }
} }
+1 -1
View File
@@ -75,7 +75,7 @@ class GetOldMessage extends \sammo\BaseAPI
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID); $me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID);
if ($me === null) { if ($me === null) {
return '장수가 사망했습니다.'; return '장수가 사망했습니다.';
+13 -1
View File
@@ -6,8 +6,10 @@ use sammo\Session;
use DateTimeInterface; use DateTimeInterface;
use sammo\DB; use sammo\DB;
use sammo\Enums\APIRecoveryType; use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralStorKey;
use sammo\Enums\MessageType; use sammo\Enums\MessageType;
use sammo\Json; use sammo\Json;
use sammo\KVStorage;
use sammo\Message; use sammo\Message;
use sammo\TimeUtil; use sammo\TimeUtil;
use sammo\Util; use sammo\Util;
@@ -71,7 +73,7 @@ class GetRecentMessage extends \sammo\BaseAPI
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID); $me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID);
if ($me === null) { if ($me === null) {
return '장수가 사망했습니다.'; return '장수가 사망했습니다.';
@@ -140,9 +142,19 @@ class GetRecentMessage extends \sammo\BaseAPI
array_pop($result[$lastType]); array_pop($result[$lastType]);
} }
$generalStor = KVStorage::getStorage($db, "general_{$generalID}");
[$latestReadDiplomacyMsg, $latestReadPrivateMsg] = $generalStor->getValuesAsArray([
GeneralStorKey::latestReadDiplomacyMsg,
GeneralStorKey::latestReadPrivateMsg
]);
$result['sequence'] = $nextSequence; $result['sequence'] = $nextSequence;
$result['nationID'] = $nationID; $result['nationID'] = $nationID;
$result['generalName'] = $generalName; $result['generalName'] = $generalName;
$result['latestRead'] = [
'diplomacy' => $latestReadDiplomacyMsg ?? 0,
'private' => $latestReadPrivateMsg ?? 0,
];
return $result; return $result;
} }
@@ -0,0 +1,52 @@
<?php
namespace sammo\API\Message;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralStorKey;
use sammo\Enums\MessageType;
use sammo\KVStorage;
use sammo\Session;
use sammo\Validator;
class ReadLatestMessage extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
//type이 개인 메시지 혹은 외교 메시지여야함
$v = new Validator($this->args);
$v->rule('required', ['type', 'msgID'])
->rule('in', 'type', [MessageType::private->value, MessageType::diplomacy->value])
->rule('int', 'msgID');
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): null | string | array | APIRecoveryType
{
$db = DB::db();
$generalID = $session->generalID;
$generalStor = KVStorage::getStorage($db, "general_{$generalID}");
$type = MessageType::from($this->args['type']);
$msgID = $this->args['msgID'];
$storKey = GeneralStorKey::latestReadPrivateMsg;
if($type == MessageType::diplomacy){
$storKey = GeneralStorKey::latestReadDiplomacyMsg;
}
$oldValue = $generalStor->getValue($storKey);
if($oldValue === null || $oldValue < $msgID){
$generalStor->setValue($storKey, $msgID);
}
return null;
}
}
+7 -4
View File
@@ -108,7 +108,7 @@ class SendMessage extends \sammo\BaseAPI
$unlimited = new \DateTime('9999-12-31'); $unlimited = new \DateTime('9999-12-31');
$db = DB::db(); $db = DB::db();
$destUser = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,permission,penalty FROM general WHERE `no`=%i', $destGeneralID); $destUser = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`picture`,`imgsvr`,permission,penalty FROM general WHERE `no`=%i', $destGeneralID);
if (!$destUser) { if (!$destUser) {
return '존재하지 않는 유저입니다.'; return '존재하지 않는 유저입니다.';
@@ -160,15 +160,18 @@ class SendMessage extends \sammo\BaseAPI
} }
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission,belong FROM general WHERE `owner`=%i', $userID); $me = $db->queryFirstRow(
'SELECT `no`,`name`,`nation`,`officer_level`,`refresh_score`,`picture`,`imgsvr`,penalty,permission,belong FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE `owner`=%i', $userID
);
if (!$me) { if (!$me) {
$session->logoutGame(); $session->logoutGame();
return '장수가 없습니다.'; return '장수가 없습니다.';
} }
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
return '접속 제한입니다.'; return '접속 제한입니다.';
} }
+31 -13
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Nation;
use ArrayObject; use ArrayObject;
use sammo\DB; use sammo\DB;
use sammo\Enums\APIRecoveryType; use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralQueryMode;
use sammo\General; use sammo\General;
use sammo\Session; use sammo\Session;
use sammo\Util; use sammo\Util;
@@ -44,12 +45,10 @@ class GeneralList extends \sammo\BaseAPI
'special2' => 0, 'special2' => 0,
'personal' => 0, 'personal' => 0,
'belong' => 0, 'belong' => 0,
'connect' => 0,
'troop' => 0, 'troop' => 0,
'city' => 0, 'city' => 0,
'con' => 1,
'specage' => 0, 'specage' => 0,
'specage2' => 0, 'specage2' => 0,
'leadership_exp' => 1, 'leadership_exp' => 1,
@@ -83,6 +82,11 @@ class GeneralList extends \sammo\BaseAPI
'owner_name' => 9, //안씀. 'owner_name' => 9, //안씀.
//accessLog
'refresh_score_total' => 0,
'refresh_score' => 1,
//RANK //RANK
'warnum' => 1, 'warnum' => 1,
'killnum' => 1, 'killnum' => 1,
@@ -95,6 +99,8 @@ class GeneralList extends \sammo\BaseAPI
static $columnRemap = [ static $columnRemap = [
'special' => 'specialDomestic', 'special' => 'specialDomestic',
'special2' => 'specialWar', 'special2' => 'specialWar',
'refresh_score_total' => 'refreshScoreTotal',
'refresh_score' => 'refreshScore',
'aux' => null, 'aux' => null,
]; ];
@@ -143,9 +149,12 @@ class GeneralList extends \sammo\BaseAPI
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env'); $gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getValues(['year', 'month', 'turntime', 'turnterm', 'autorun_user', 'killturn']); $env = $gameStor->getValues(['year', 'month', 'turntime', 'turnterm', 'autorun_user', 'killturn']);
$me = $db->queryFirstRow('SELECT con, turntime, belong, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $session->getUserID()); $me = $db->queryFirstRow(
$con = checkLimit($me['con']); 'SELECT refresh_score, turntime, belong, nation, officer_level, permission, penalty FROM `general`
if ($con >= 2) { LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $session->getUserID()
);
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'; return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.';
} }
@@ -156,9 +165,18 @@ class GeneralList extends \sammo\BaseAPI
[$queryColumns, $rankColumns] = General::mergeQueryColumn(array_keys(static::$viewColumns), 1); [$queryColumns, $rankColumns, $accessLogColumns] = General::mergeQueryColumn(array_keys(static::$viewColumns), GeneralQueryMode::Lite);
$rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE nation = %i ORDER BY turntime ASC', Util::formatListOfBackticks($queryColumns), $nationID), 'no'); $rawGeneralList = Util::convertArrayToDict(
$db->query(
'SELECT %l, %l from `general` LEFT JOIN general_access_log
ON `general`.`no` = general_access_log.general_id WHERE nation = %i ORDER BY turntime ASC',
Util::formatListOfBackticks($queryColumns),
Util::formatListOfBackticks($accessLogColumns),
$nationID
),
'no'
);
/** @var ArrayObject[] */ /** @var ArrayObject[] */
$troops = []; $troops = [];
@@ -179,19 +197,19 @@ class GeneralList extends \sammo\BaseAPI
if ($this->permission >= 1 || count($troops)) { if ($this->permission >= 1 || count($troops)) {
$reservedCommandTargetGeneralIDList = []; $reservedCommandTargetGeneralIDList = [];
if($this->permission >= 1){ if ($this->permission >= 1) {
foreach ($rawGeneralList as $rawGeneral) { foreach ($rawGeneralList as $rawGeneral) {
if ($rawGeneral['npc'] < 2) { if ($rawGeneral['npc'] < 2) {
$reservedCommandTargetGeneralIDList[$rawGeneral['no']] = $rawGeneral['no']; $reservedCommandTargetGeneralIDList[$rawGeneral['no']] = $rawGeneral['no'];
} }
} }
} }
foreach($troops as $troop){ foreach ($troops as $troop) {
$reservedCommandTargetGeneralIDList[$troop['id']] = $troop['id']; $reservedCommandTargetGeneralIDList[$troop['id']] = $troop['id'];
} }
if($reservedCommandTargetGeneralIDList){ if ($reservedCommandTargetGeneralIDList) {
$rawTurnList = $db->query( $rawTurnList = $db->query(
'SELECT general_id, turn_idx, action, arg, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id asc, turn_idx asc', 'SELECT general_id, turn_idx, action, arg, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id asc, turn_idx asc',
array_values($reservedCommandTargetGeneralIDList) array_values($reservedCommandTargetGeneralIDList)
@@ -278,11 +296,11 @@ class GeneralList extends \sammo\BaseAPI
$resultColumns[$column] = $column; $resultColumns[$column] = $column;
} }
foreach ($troops as $troop){ foreach ($troops as $troop) {
$troopLeaderID = $troop['id']; $troopLeaderID = $troop['id'];
$troop['reservedCommand'] = array_map(function($turnObj){ $troop['reservedCommand'] = array_map(function ($turnObj) {
$brief = $turnObj['brief']; $brief = $turnObj['brief'];
if($brief == '집합'){ if ($brief == '집합') {
return $brief; return $brief;
} }
return '-'; return '-';
+5 -3
View File
@@ -109,10 +109,12 @@ class GetGeneralLog extends \sammo\BaseAPI
$reqTo = $this->args['reqTo'] ?? null; $reqTo = $this->args['reqTo'] ?? null;
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,permission,penalty from general where owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no,nation,officer_level,refresh_score,turntime,belong,permission,penalty FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID);
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
return '접속 제한입니다.'; return '접속 제한입니다.';
} }
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\Nation;
use sammo\DB; use sammo\DB;
use sammo\Enums\APIRecoveryType; use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralQueryMode;
use sammo\GameConst; use sammo\GameConst;
use sammo\General; use sammo\General;
use sammo\KVStorage; use sammo\KVStorage;
@@ -65,7 +66,7 @@ class GetNationInfo extends \sammo\BaseAPI
]; ];
} }
$generalObj = General::createGeneralObjFromDB($session->generalID, null, 1); $generalObj = General::createGeneralObjFromDB($session->generalID, null, GeneralQueryMode::FullWithoutIAction);
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$gameEnv = $gameStor->getValues(['year', 'month', 'startyear']); $gameEnv = $gameStor->getValues(['year', 'month', 'startyear']);
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface; use DateTimeInterface;
use sammo\DB; use sammo\DB;
use sammo\Enums\APIRecoveryType; use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralQueryMode;
use sammo\GameConst; use sammo\GameConst;
use sammo\General; use sammo\General;
use sammo\Json; use sammo\Json;
@@ -39,12 +40,15 @@ class GetReservedCommand extends \sammo\BaseAPI
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$userID = $session->userID; $userID = $session->userID;
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,penalty,permission FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow(
'SELECT no,nation,officer_level,refresh_score,turntime,belong,penalty,permission FROM `general`
LEFT JOIN general_access_log AS l ON `general`.no = l.general_id WHERE owner=%i', $userID
);
$nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation = %i', $me['nation']); $nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation = %i', $me['nation']);
$nationID = $me['nation']; $nationID = $me['nation'];
$con = checkLimit($me['con']); $limitState = checkLimit($me['refresh_score']);
if ($con >= 2) { if ($limitState >= 2) {
return "접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 갱신 가능 시각 : {$me['turntime']})"; return "접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 갱신 가능 시각 : {$me['turntime']})";
} }
@@ -59,7 +63,7 @@ class GetReservedCommand extends \sammo\BaseAPI
$generals = []; $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) { 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); $generals[$rawGeneral['officer_level']] = new General($rawGeneral, null, null, null, null, $year, $month, false);
} }
$nationTurnList = []; $nationTurnList = [];
@@ -109,7 +113,7 @@ class GetReservedCommand extends \sammo\BaseAPI
]; ];
} }
$generalObj = General::createGeneralObjFromDB($session->generalID); $generalObj = General::createGeneralObjFromDB($session->generalID, null, GeneralQueryMode::FullWithoutIAction);
return [ return [
+2 -1
View File
@@ -6,6 +6,7 @@ use DateTimeInterface;
use sammo\DB; use sammo\DB;
use sammo\DTO\VoteComment; use sammo\DTO\VoteComment;
use sammo\Enums\APIRecoveryType; use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralQueryMode;
use sammo\General; use sammo\General;
use sammo\Session; use sammo\Session;
use sammo\TimeUtil; use sammo\TimeUtil;
@@ -40,7 +41,7 @@ class AddComment extends \sammo\BaseAPI
$text = mb_substr($this->args['text'], 0, 200); $text = mb_substr($this->args['text'], 0, 200);
$generalID = $session->generalID; $generalID = $session->generalID;
$general = General::createGeneralObjFromDB($generalID, [], 0); $general = General::createGeneralObjFromDB($generalID, null, GeneralQueryMode::Core);
$generalName = $general->getName(); $generalName = $general->getName();
$nationID = $general->getNationID(); $nationID = $general->getNationID();
$nationName = $general->getStaticNation()['name']; $nationName = $general->getStaticNation()['name'];
+2 -1
View File
@@ -6,6 +6,7 @@ use DateTimeInterface;
use sammo\DB; use sammo\DB;
use sammo\DTO\VoteInfo; use sammo\DTO\VoteInfo;
use sammo\Enums\APIRecoveryType; use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralQueryMode;
use sammo\General; use sammo\General;
use sammo\Json; use sammo\Json;
use sammo\KVStorage; use sammo\KVStorage;
@@ -105,7 +106,7 @@ class Vote extends \sammo\BaseAPI
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$voteReward = $gameStor->getValue('develcost') * 5; $voteReward = $gameStor->getValue('develcost') * 5;
$general = General::createGeneralObjFromDB($generalID, ['gold', 'horse', 'weapon', 'book', 'item', 'npc', 'imgsvr', 'picture', 'aux'], 2); $general = General::createGeneralObjFromDB($generalID, ['gold', 'horse', 'weapon', 'book', 'item', 'npc', 'imgsvr', 'picture', 'aux'], GeneralQueryMode::Lite);
$general->increaseVar('gold', $voteReward); $general->increaseVar('gold', $voteReward);
$uniqueRng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize( $uniqueRng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed, UniqueConst::$hiddenSeed,
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace sammo\ActionCrewType;
use \sammo\iAction;
use \sammo\General;
class None implements iAction{
use \sammo\DefaultAction;
protected $id = -1;
protected $name = '-';
protected $info = '';
}
@@ -0,0 +1,20 @@
<?php
namespace sammo\ActionCrewType;
use \sammo\iAction;
use \sammo\General;
class che_성벽선제 implements iAction{
use \sammo\DefaultAction;
protected $name = '성벽선제';
protected $info = '전투 가능한 성벽이라면 선제공격을 합니다.';
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
if($statName == 'cityBattleOrder'){
// battleOrder는 스탯과 유사한 수치를 가지므로, 아주 충분히 높은값을 설정한다.
return 10000;
}
return $value;
}
}
+3 -3
View File
@@ -25,15 +25,15 @@ class che_병가 extends \sammo\BaseNation{
if($varType == 'score') return $value * 0.9; if($varType == 'score') return $value * 0.9;
if($varType == 'cost') return $value * 1.2; if($varType == 'cost') return $value * 1.2;
} }
return $value; return $value;
} }
public function onCalcNationalIncome(string $type, $amount):int{ public function onCalcNationalIncome(string $type, $amount):int{
if($type == 'pop' && $amount > 0){ if($type == 'pop' && $amount > 0){
return Util::toInt($amount * 0.8); return $amount * 0.8;
} }
return $amount; return $amount;
} }
} }
+3 -2
View File
@@ -5,6 +5,7 @@ namespace sammo;
use Ds\Map; use Ds\Map;
use sammo\DTO\BettingInfo; use sammo\DTO\BettingInfo;
use sammo\DTO\BettingItem; use sammo\DTO\BettingItem;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\RankColumn; use sammo\Enums\RankColumn;
class Betting class Betting
@@ -243,7 +244,7 @@ class Betting
return $this->_calcRewardExclusive($winnerType); return $this->_calcRewardExclusive($winnerType);
} }
if ($this->info->isExlusive) { if ($this->info->isExclusive) {
return $this->_calcRewardExclusive($winnerType); return $this->_calcRewardExclusive($winnerType);
} }
//아래는 2개 이상, 복합 보상 옵션 //아래는 2개 이상, 복합 보상 옵션
@@ -401,7 +402,7 @@ class Betting
$userLogger->flush(); $userLogger->flush();
} }
} else { } else {
$generalList = General::createGeneralObjListFromDB(array_unique(Util::squeezeFromArray($rewardList, 'generalID')), ['gold', 'npc', 'betgold'], 1); $generalList = General::createGeneralObjListFromDB(array_unique(Util::squeezeFromArray($rewardList, 'generalID')), ['gold', 'npc', 'betgold'], GeneralQueryMode::Lite);
foreach ($rewardList as $rewardItem) { foreach ($rewardList as $rewardItem) {
$gambler = $generalList[$rewardItem['generalID']]; $gambler = $generalList[$rewardItem['generalID']];
$reward = Util::round($rewardItem['amount']); $reward = Util::round($rewardItem['amount']);
+2 -2
View File
@@ -21,7 +21,7 @@ use function \sammo\getNationStaticInfo;
use function sammo\tryUniqueItemLottery; use function sammo\tryUniqueItemLottery;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
class che_등용 extends Command\GeneralCommand class che_등용 extends Command\GeneralCommand
{ {
@@ -77,7 +77,7 @@ class che_등용 extends Command\GeneralCommand
protected function initWithArg() protected function initWithArg()
{ {
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['nation', 'experience', 'dedication'], 0); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['nation', 'experience', 'dedication'], GeneralQueryMode::Lite);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
[$reqGold, $reqRice] = $this->getCost(); [$reqGold, $reqRice] = $this->getCost();
@@ -68,7 +68,7 @@ class che_등용수락 extends Command\GeneralCommand{
protected function initWithArg() protected function initWithArg()
{ {
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, 2); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
$this->setDestNation($this->arg['destNationID'], ['gennum', 'scout']); $this->setDestNation($this->arg['destNationID'], ['gennum', 'scout']);
@@ -77,6 +77,7 @@ class che_등용수락 extends Command\GeneralCommand{
$this->fullConditionConstraints=[ $this->fullConditionConstraints=[
ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'), ConstraintHelper::ReqEnvValue('join_mode', '!=', 'onlyRandom', '랜덤 임관만 가능합니다'),
ConstraintHelper::ExistsDestNation(), ConstraintHelper::ExistsDestNation(),
ConstraintHelper::BeNeutral(),
ConstraintHelper::AllowJoinDestNation($relYear), ConstraintHelper::AllowJoinDestNation($relYear),
ConstraintHelper::ReqDestNationValue('level', '국가규모', '>', 0, '방랑군에는 임관할 수 없습니다.'), ConstraintHelper::ReqDestNationValue('level', '국가규모', '>', 0, '방랑군에는 임관할 수 없습니다.'),
ConstraintHelper::DifferentDestNation(), ConstraintHelper::DifferentDestNation(),
+24 -4
View File
@@ -21,6 +21,7 @@ use \sammo\Constraint\ConstraintHelper;
class che_물자조달 extends Command\GeneralCommand{ class che_물자조달 extends Command\GeneralCommand{
static protected $actionName = '물자조달'; static protected $actionName = '물자조달';
static protected $debuffFront = 0.5;
protected function argTest():bool{ protected function argTest():bool{
$this->arg = null; $this->arg = null;
@@ -95,10 +96,32 @@ class che_물자조달 extends Command\GeneralCommand{
$score = $general->onCalcDomestic('조달', 'score', $score); $score = $general->onCalcDomestic('조달', 'score', $score);
$score = Util::round($score); $score = Util::round($score);
$scoreText = number_format($score, 0);
$exp = $score * 0.7 / 3;
$ded = $score * 1.0 / 3;
$logger = $general->getLogger(); $logger = $general->getLogger();
if(in_array($this->city['front'], [1, 3])){
$debuffFront = static::$debuffFront;
if($this->nation['capital'] == $this->city['city']){
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
[$year, $startYear] = $gameStor->getValuesAsArray(['year', 'startyear']);
$relYear = $year - $startYear;
if($relYear < 25){
$debuffScale = Util::clamp($relYear - 5, 0, 20) * 0.05;
$debuffFront = ($debuffScale * $debuffFront) + (1 - $debuffScale);
}
}
$score *= $debuffFront;
}
$scoreText = number_format($score, 0);
if($pick == 'fail'){ if($pick == 'fail'){
$logger->pushGeneralActionLog("조달을 <span class='ev_failed'>실패</span>하여 {$resName}을 <C>$scoreText</> 조달했습니다. <1>$date</>"); $logger->pushGeneralActionLog("조달을 <span class='ev_failed'>실패</span>하여 {$resName}을 <C>$scoreText</> 조달했습니다. <1>$date</>");
} }
@@ -109,9 +132,6 @@ class che_물자조달 extends Command\GeneralCommand{
$logger->pushGeneralActionLog("{$resName}을 <C>$scoreText</> 조달했습니다. <1>$date</>"); $logger->pushGeneralActionLog("{$resName}을 <C>$scoreText</> 조달했습니다. <1>$date</>");
} }
$exp = $score * 0.7 / 3;
$ded = $score * 1.0 / 3;
$incStat = $rng->choiceUsingWeight([ $incStat = $rng->choiceUsingWeight([
'leadership_exp'=>$general->getLeadership(false, false, false, false), 'leadership_exp'=>$general->getLeadership(false, false, false, false),
'strength_exp'=>$general->getStrength(false, false, false, false), 'strength_exp'=>$general->getStrength(false, false, false, false),
+15 -2
View File
@@ -185,8 +185,21 @@ class che_상업투자 extends Command\GeneralCommand{
$logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>"); $logger->pushGeneralActionLog(static::$actionName."{$josaUl} 하여 <C>$scoreText</> 상승했습니다. <1>$date</>");
} }
if(in_array($this->city['front'], [1, 3]) && $this->nation['capital'] != $this->city['city']){ if(in_array($this->city['front'], [1, 3])){
$score *= static::$debuffFront; $debuffFront = static::$debuffFront;
if($this->nation['capital'] == $this->city['city']){
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
[$year, $startYear] = $gameStor->getValuesAsArray(['year', 'startyear']);
$relYear = $year - $startYear;
if($relYear < 25){
$debuffScale = Util::clamp($relYear - 5, 0, 20) * 0.05;
$debuffFront = ($debuffScale * $debuffFront) + (1 - $debuffScale);
}
}
$score *= $debuffFront;
} }
//NOTE: 내정량 상승시 초과 가능? //NOTE: 내정량 상승시 초과 가능?
+2 -1
View File
@@ -19,6 +19,7 @@ use function\sammo\tryUniqueItemLottery;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\InheritanceKey; use sammo\Enums\InheritanceKey;
class che_선양 extends Command\GeneralCommand class che_선양 extends Command\GeneralCommand
@@ -65,7 +66,7 @@ class che_선양 extends Command\GeneralCommand
protected function initWithArg() protected function initWithArg()
{ {
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'nation'], 1); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'nation'], GeneralQueryMode::Lite);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
$this->fullConditionConstraints = [ $this->fullConditionConstraints = [
@@ -17,6 +17,7 @@ use function \sammo\tryUniqueItemLottery;
use function \sammo\getNationStaticInfo; use function \sammo\getNationStaticInfo;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\InheritanceKey; use sammo\Enums\InheritanceKey;
class che_장수대상임관 extends Command\GeneralCommand{ class che_장수대상임관 extends Command\GeneralCommand{
@@ -83,7 +84,7 @@ class che_장수대상임관 extends Command\GeneralCommand{
protected function initWithArg() protected function initWithArg()
{ {
$destGeneralID = $this->arg['destGeneralID']; $destGeneralID = $this->arg['destGeneralID'];
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['nation'], 0); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['nation'], GeneralQueryMode::Lite);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
$this->setDestNation($this->destGeneralObj->getVar('nation'), ['gennum', 'scout']); $this->setDestNation($this->destGeneralObj->getVar('nation'), ['gennum', 'scout']);
@@ -87,6 +87,12 @@ class che_전투특기초기화 extends Command\GeneralCommand{
$yearMonth = Util::joinYearMonth($env['year'], $env['month']); $yearMonth = Util::joinYearMonth($env['year'], $env['month']);
$oldSpecialList = $general->getAuxVar($oldTypeKey)??[]; $oldSpecialList = $general->getAuxVar($oldTypeKey)??[];
$oldSpecialList[] = $general->getVar(static::$specialType); $oldSpecialList[] = $general->getVar(static::$specialType);
if(static::$specialType == 'special' && count($oldSpecialList) == count(GameConst::$availableSpecialDomestic)){
$oldSpecialList = [$general->getVar(static::$specialType)];
}
else if(static::$specialType == 'special2' && count($oldSpecialList) == count(GameConst::$availableSpecialWar)){
$oldSpecialList = [$general->getVar(static::$specialType)];
}
$general->setAuxVar($oldTypeKey, $oldSpecialList); $general->setAuxVar($oldTypeKey, $oldSpecialList);
$general->setVar(static::$specialType, 'None'); $general->setVar(static::$specialType, 'None');
+2 -1
View File
@@ -15,6 +15,7 @@ use \sammo\Command;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
use function sammo\tryUniqueItemLottery; use function sammo\tryUniqueItemLottery;
@@ -86,7 +87,7 @@ class che_증여 extends Command\GeneralCommand
protected function initWithArg() protected function initWithArg()
{ {
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'nation'], 1); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'nation'], GeneralQueryMode::Lite);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
$this->fullConditionConstraints = [ $this->fullConditionConstraints = [
+2 -1
View File
@@ -15,6 +15,7 @@ use function \sammo\searchDistance;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst; use sammo\CityConst;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\RankColumn; use sammo\Enums\RankColumn;
use sammo\RandUtil; use sammo\RandUtil;
@@ -268,7 +269,7 @@ class che_화계 extends Command\GeneralCommand
$destCityGeneralList = []; $destCityGeneralList = [];
$cityGeneralID = $db->queryFirstColumn('SELECT no FROM general WHERE city = %i AND nation = %i', $destCityID, $destNationID); $cityGeneralID = $db->queryFirstColumn('SELECT no FROM general WHERE city = %i AND nation = %i', $destCityID, $destNationID);
$destCityGeneralList = General::createGeneralObjListFromDB($cityGeneralID, ['name', 'city', 'nation', 'officer_level', 'leadership', 'horse', 'strength', 'weapon', 'intel', 'book', 'item', 'last_turn', 'injury', 'special', 'special2', 'injury', 'crewtype', 'crew', 'atmos', 'train'], 2); $destCityGeneralList = General::createGeneralObjListFromDB($cityGeneralID, ['name', 'city', 'nation', 'officer_level', 'leadership', 'horse', 'strength', 'weapon', 'intel', 'book', 'item', 'last_turn', 'injury', 'special', 'special2', 'injury', 'crewtype', 'crew', 'atmos', 'train']);
foreach ($destCityGeneralList as &$destCityGeneral) { foreach ($destCityGeneralList as &$destCityGeneral) {
$destCityGeneral->setRawCity($this->destCity); $destCityGeneral->setRawCity($this->destCity);
unset($destCityGeneral); unset($destCityGeneral);
+7 -4
View File
@@ -19,6 +19,7 @@ use function \sammo\GetImageURL;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\MessageType; use sammo\Enums\MessageType;
class che_몰수 extends Command\NationCommand class che_몰수 extends Command\NationCommand
@@ -91,7 +92,7 @@ class che_몰수 extends Command\NationCommand
protected function initWithArg() protected function initWithArg()
{ {
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'npc', 'nation', 'imgsvr', 'picture'], 1); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'npc', 'nation', 'imgsvr', 'picture'], GeneralQueryMode::Lite);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
$env = $this->env; $env = $this->env;
@@ -173,7 +174,7 @@ class che_몰수 extends Command\NationCommand
$npcTexts = [ $npcTexts = [
'몰수를 하다니... 이것이 윗사람이 할 짓이란 말입니까...', '몰수를 하다니... 이것이 윗사람이 할 짓이란 말입니까...',
'사유재산까지 몰수해가면서 이 나라가 잘 될거라 믿습니까? 정말 이해할 수가 없군요...', '사유재산까지 몰수해가면서 이 나라가 잘 될거라 믿습니까? 정말 이해할 수가 없군요...',
'내 돈 내놔라! 내 돈! 몰수가 말이냐!', '내 돈 내놔라! 내 돈! 몰수가 말이냐!',
'몰수해간 내 자금... 언젠가 몰래 다시 빼내올 것이다...', '몰수해간 내 자금... 언젠가 몰래 다시 빼내올 것이다...',
'몰수로 인한 사기 저하는 몰수로 얻은 물자보다 더 손해란걸 모른단 말인가!' '몰수로 인한 사기 저하는 몰수로 얻은 물자보다 더 손해란걸 모른단 말인가!'
]; ];
@@ -205,8 +206,10 @@ class che_몰수 extends Command\NationCommand
$resKey => $db->sqleval('%b + %i', $resKey, $amount) $resKey => $db->sqleval('%b + %i', $resKey, $amount)
], 'nation=%i', $nationID); ], 'nation=%i', $nationID);
$destGeneral->getLogger()->pushGeneralActionLog("{$resName} {$amountText}을 몰수 당했습니다.", ActionLogger::PLAIN); $josaUl = JosaUtil::pick($amountText, '을');
$logger->pushGeneralActionLog("<Y>{$destGeneral->getName()}</>에게서 {$resName} <C>$amountText</>을 몰수했습니다. <1>$date</>");
$destGeneral->getLogger()->pushGeneralActionLog("{$resName} {$amountText}{$josaUl} 몰수 당했습니다.", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("<Y>{$destGeneral->getName()}</>에게서 {$resName} <C>$amountText</>{$josaUl} 몰수했습니다. <1>$date</>");
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->applyDB($db); $general->applyDB($db);
@@ -215,14 +215,16 @@ class che_물자원조 extends Command\NationCommand
$chiefLogger->flush(); $chiefLogger->flush();
} }
$logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원"); $josaUlRiceAmount = JosaUtil::pick($riceAmountText, '을');
$logger->pushNationalHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원");
$logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>{$josaUlRiceAmount} 지원");
$logger->pushNationalHistoryLog("<D><b>{$destNationName}</b></>{$josaRo} 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>{$josaUlRiceAmount} 지원");
$logger->pushGlobalHistoryLog("<Y><b>【원조】</b></><D><b>{$nationName}</b></>에서 <D><b>{$destNationName}</b></>{$josaRo} 물자를 지원합니다"); $logger->pushGlobalHistoryLog("<Y><b>【원조】</b></><D><b>{$nationName}</b></>에서 <D><b>{$destNationName}</b></>{$josaRo} 물자를 지원합니다");
$logger->pushGeneralActionLog($broadcastMessage); $logger->pushGeneralActionLog($broadcastMessage);
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 물자를 지원합니다. <1>$date</>", ActionLogger::PLAIN); $logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 물자를 지원합니다. <1>$date</>", ActionLogger::PLAIN);
$destBroadcastMessage = $broadcastMessage = "<D><b>{$nationName}</b></>에서 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</> 원조했습니다."; $destBroadcastMessage = $broadcastMessage = "<D><b>{$nationName}</b></>에서 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>{$josaUlRiceAmount} 원조했습니다.";
$destChiefList = $db->queryFirstColumn('SELECT no FROM general WHERE officer_level >= 5 AND nation = %i', $destNationID); $destChiefList = $db->queryFirstColumn('SELECT no FROM general WHERE officer_level >= 5 AND nation = %i', $destNationID);
foreach ($destChiefList as $destChiefID) { foreach ($destChiefList as $destChiefID) {
$destChiefLogger = new ActionLogger($destChiefID, $nationID, $year, $month); $destChiefLogger = new ActionLogger($destChiefID, $nationID, $year, $month);
@@ -232,7 +234,7 @@ class che_물자원조 extends Command\NationCommand
$josaRoSrc = JosaUtil::pick($nationName, '로'); $josaRoSrc = JosaUtil::pick($nationName, '로');
$destNationLogger = new ActionLogger(0, $destNationID, $year, $month); $destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaRoSrc}부터 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</> 지원 받음"); $destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaRoSrc}부터 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>{$josaUlRiceAmount} 지원 받음");
$destNationStor = KVStorage::getStorage(DB::db(), $destNationID, 'nation_env'); $destNationStor = KVStorage::getStorage(DB::db(), $destNationID, 'nation_env');
$destRecvAssist = $destNationStor->getValue('recv_assist') ?? []; $destRecvAssist = $destNationStor->getValue('recv_assist') ?? [];
+2 -1
View File
@@ -21,6 +21,7 @@ use function \sammo\cutTurn;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
class che_발령 extends Command\NationCommand class che_발령 extends Command\NationCommand
{ {
@@ -71,7 +72,7 @@ class che_발령 extends Command\NationCommand
{ {
$this->setDestCity($this->arg['destCityID']); $this->setDestCity($this->arg['destCityID']);
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, 1); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, GeneralQueryMode::Lite);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
if ($this->arg['destGeneralID'] == $this->getGeneral()->getID()) { if ($this->arg['destGeneralID'] == $this->getGeneral()->getID()) {
@@ -20,6 +20,7 @@ use function \sammo\getNationStaticInfo;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
use sammo\Json; use sammo\Json;
use sammo\KVStorage; use sammo\KVStorage;
use sammo\RandUtil; use sammo\RandUtil;
@@ -103,7 +104,7 @@ class che_불가침수락 extends Command\NationCommand
$env = $this->env; $env = $this->env;
$relYear = $env['year'] - $env['startyear']; $relYear = $env['year'] - $env['startyear'];
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], [], 1); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, GeneralQueryMode::Lite);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
$this->setDestNation($this->arg['destNationID']); $this->setDestNation($this->arg['destNationID']);
@@ -165,6 +165,7 @@ class che_불가침제의 extends Command\NationCommand
$nation = $this->nation; $nation = $this->nation;
$nationID = $nation['nation']; $nationID = $nation['nation'];
$nationName = $nation['name']; $nationName = $nation['name'];
$josaRo = JosaUtil::pick($nationName, '로');
$destNation = $this->destNation; $destNation = $this->destNation;
$destNationID = $destNation['nation']; $destNationID = $destNation['nation'];
@@ -176,7 +177,7 @@ class che_불가침제의 extends Command\NationCommand
$logger = $general->getLogger(); $logger = $general->getLogger();
$destLogger = new ActionLogger(0, $destNationID, $env['year'], $env['month']); $destLogger = new ActionLogger(0, $destNationID, $env['year'], $env['month']);
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>으로 불가침 제의 서신을 보냈습니다.<1>$date</>"); $logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 불가침 제의 서신을 보냈습니다.<1>$date</>");
// 상대에게 발송 // 상대에게 발송
$src = new MessageTarget( $src = new MessageTarget(
@@ -20,6 +20,7 @@ use function \sammo\getNationStaticInfo;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
use sammo\RandUtil; use sammo\RandUtil;
class che_불가침파기수락 extends Command\NationCommand class che_불가침파기수락 extends Command\NationCommand
@@ -77,7 +78,7 @@ class che_불가침파기수락 extends Command\NationCommand
protected function initWithArg() protected function initWithArg()
{ {
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], [], 1); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, GeneralQueryMode::Lite);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
$this->setDestNation($this->arg['destNationID']); $this->setDestNation($this->arg['destNationID']);
@@ -122,11 +122,12 @@ class che_불가침파기제의 extends Command\NationCommand{
$destNation = $this->destNation; $destNation = $this->destNation;
$destNationID = $destNation['nation']; $destNationID = $destNation['nation'];
$destNationName = $destNation['name']; $destNationName = $destNation['name'];
$josaRo = JosaUtil::pick($destNationName, '로');
$logger = $general->getLogger(); $logger = $general->getLogger();
$destLogger = new ActionLogger(0, $destNationID, $env['year'], $env['month']); $destLogger = new ActionLogger(0, $destNationID, $env['year'], $env['month']);
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>으로 불가침 파기 제의 서신을 보냈습니다.<1>$date</>"); $logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 불가침 파기 제의 서신을 보냈습니다.<1>$date</>");
// 상대에게 발송 // 상대에게 발송
$src = new MessageTarget( $src = new MessageTarget(
@@ -22,6 +22,7 @@ use function \sammo\getNationStaticInfo;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
class che_종전수락 extends Command\NationCommand class che_종전수락 extends Command\NationCommand
{ {
@@ -86,7 +87,7 @@ class che_종전수락 extends Command\NationCommand
protected function initWithArg() protected function initWithArg()
{ {
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], [], 1); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], null, GeneralQueryMode::Lite);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
$this->setDestNation($this->arg['destNationID']); $this->setDestNation($this->arg['destNationID']);
@@ -120,11 +120,12 @@ class che_종전제의 extends Command\NationCommand{
$destNation = $this->destNation; $destNation = $this->destNation;
$destNationID = $destNation['nation']; $destNationID = $destNation['nation'];
$destNationName = $destNation['name']; $destNationName = $destNation['name'];
$josaRo = JosaUtil::pick($destNationName, '로');
$logger = $general->getLogger(); $logger = $general->getLogger();
$destLogger = new ActionLogger(0, $destNationID, $env['year'], $env['month']); $destLogger = new ActionLogger(0, $destNationID, $env['year'], $env['month']);
$logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>으로 종전 제의 서신을 보냈습니다.<1>$date</>"); $logger->pushGeneralActionLog("<D><b>{$destNationName}</b></>{$josaRo} 종전 제의 서신을 보냈습니다.<1>$date</>");
// 상대에게 발송 // 상대에게 발송
$src = new MessageTarget( $src = new MessageTarget(
+6 -3
View File
@@ -15,6 +15,7 @@ use \sammo\Command;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
class che_포상 extends Command\NationCommand class che_포상 extends Command\NationCommand
{ {
@@ -81,7 +82,7 @@ class che_포상 extends Command\NationCommand
protected function initWithArg() protected function initWithArg()
{ {
$destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'nation'], 1); $destGeneral = General::createGeneralObjFromDB($this->arg['destGeneralID'], ['gold', 'rice', 'nation'], GeneralQueryMode::Lite);
$this->setDestGeneral($destGeneral); $this->setDestGeneral($destGeneral);
if($this->arg['destGeneralID'] == $this->getGeneral()->getID()){ if($this->arg['destGeneralID'] == $this->getGeneral()->getID()){
@@ -167,8 +168,10 @@ class che_포상 extends Command\NationCommand
$resKey => $db->sqleval('%b - %i', $resKey, $amount) $resKey => $db->sqleval('%b - %i', $resKey, $amount)
], 'nation=%i', $nationID); ], 'nation=%i', $nationID);
$destGeneral->getLogger()->pushGeneralActionLog("{$resName} <C>{$amountText}</>을 포상으로 받았습니다.", ActionLogger::PLAIN); $josaUl = JosaUtil::pick($amountText, '을');
$logger->pushGeneralActionLog("<Y>{$destGeneral->getName()}</>에게 {$resName} <C>$amountText</>을 수여했습니다. <1>$date</>");
$destGeneral->getLogger()->pushGeneralActionLog("{$resName} <C>{$amountText}</>{$josaUl} 포상으로 받았습니다.", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("<Y>{$destGeneral->getName()}</>에게 {$resName} <C>$amountText</>{$josaUl} 수여했습니다. <1>$date</>");
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->applyDB($db); $general->applyDB($db);
@@ -15,6 +15,7 @@ use \sammo\{
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\GeneralQueryMode;
use sammo\Event\Action; use sammo\Event\Action;
class che_필사즉생 extends Command\NationCommand{ class che_필사즉생 extends Command\NationCommand{
@@ -94,7 +95,7 @@ class che_필사즉생 extends Command\NationCommand{
$broadcastMessage = "<Y>{$generalName}</>{$josaYi} <M>필사즉생</>을 발동하였습니다."; $broadcastMessage = "<Y>{$generalName}</>{$josaYi} <M>필사즉생</>을 발동하였습니다.";
$targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID); $targetGeneralList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND no != %i', $nationID, $generalID);
foreach(General::createGeneralObjListFromDB($targetGeneralList, ['train', 'atmos'], 1) as $targetGeneral){ foreach(General::createGeneralObjListFromDB($targetGeneralList, ['train', 'atmos'], GeneralQueryMode::Lite) as $targetGeneral){
$targetGeneral->getLogger()->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN); $targetGeneral->getLogger()->pushGeneralActionLog($broadcastMessage, ActionLogger::PLAIN);
if($targetGeneral->getVar('train') < 100){ if($targetGeneral->getVar('train') < 100){
$targetGeneral->setVar('train', 100); $targetGeneral->setVar('train', 100);
@@ -39,7 +39,7 @@ class ReqGeneralCrewMargin extends Constraint{
//XXX: 왜 General -> obj -> General 변환을 하고 있나? //XXX: 왜 General -> obj -> General 변환을 하고 있나?
//FIXME: RankVar, city에 따라 통솔이 바뀐다면 이 부분에 문제가 발생. //FIXME: RankVar, city에 따라 통솔이 바뀐다면 이 부분에 문제가 발생.
$generalObj = new General($this->general, null, null, null, null, null, true); $generalObj = new General($this->general, null, null, null, null, null, null, true);
if($reqCrewType->id != $generalObj->getCrewTypeObj()->id){ if($reqCrewType->id != $generalObj->getCrewTypeObj()->id){
return true; return true;
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace sammo\DTO;
use LDTO\Attr\Convert;
use LDTO\Attr\NullIsUndefined;
use LDTO\Attr\RawName;
use LDTO\Converter\DateTimeConverter;
class GeneralAccessLog extends \LDTO\DTO
{
public function __construct(
#[NullIsUndefined]
public ?int $id,
#[RawName('general_id')]
public int $generalID,
#[RawName('user_id')]
public ?int $userID,
#[RawName('last_refresh')]
#[Convert(DateTimeConverter::class)]
public \DateTimeImmutable $lastRefresh,
public int $refresh,
#[RawName('refresh_total')]
public int $refreshTotal,
#[RawName('refresh_score')]
public int $refreshScore,
#[RawName('refresh_score_total')]
public int $refreshScoreTotal,
) {
}
}
+4 -3
View File
@@ -1,6 +1,7 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\MessageType; use sammo\Enums\MessageType;
class DiplomaticMessage extends Message{ class DiplomaticMessage extends Message{
@@ -75,7 +76,7 @@ class DiplomaticMessage extends Message{
$gameStor = KVStorage::getStorage(DB::db(), 'game_env'); $gameStor = KVStorage::getStorage(DB::db(), 'game_env');
$destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], 1); $destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], GeneralQueryMode::Lite);
$commandObj = buildNationCommandClass('che_불가침수락', $destGeneralObj, $gameStor->getAll(true), new LastTurn(), [ $commandObj = buildNationCommandClass('che_불가침수락', $destGeneralObj, $gameStor->getAll(true), new LastTurn(), [
'destNationID'=>$this->src->nationID, 'destNationID'=>$this->src->nationID,
@@ -99,7 +100,7 @@ class DiplomaticMessage extends Message{
protected function cancelNA(){ protected function cancelNA(){
$gameStor = KVStorage::getStorage(DB::db(), 'game_env'); $gameStor = KVStorage::getStorage(DB::db(), 'game_env');
$destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], 1); $destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], GeneralQueryMode::Lite);
$commandObj = buildNationCommandClass('che_불가침파기수락', $destGeneralObj, $gameStor->getAll(true), new LastTurn(), [ $commandObj = buildNationCommandClass('che_불가침파기수락', $destGeneralObj, $gameStor->getAll(true), new LastTurn(), [
'destNationID'=>$this->src->nationID, 'destNationID'=>$this->src->nationID,
@@ -121,7 +122,7 @@ class DiplomaticMessage extends Message{
protected function stopWar(){ protected function stopWar(){
$gameStor = KVStorage::getStorage(DB::db(), 'game_env'); $gameStor = KVStorage::getStorage(DB::db(), 'game_env');
$destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], 1); $destGeneralObj = General::createGeneralObjFromDB($this->dest->generalID, ['picture', 'imgsvr', 'aux'], GeneralQueryMode::Lite);
$commandObj = buildNationCommandClass('che_종전수락', $destGeneralObj, $gameStor->getAll(true), new LastTurn(), [ $commandObj = buildNationCommandClass('che_종전수락', $destGeneralObj, $gameStor->getAll(true), new LastTurn(), [
'destNationID'=>$this->src->nationID, 'destNationID'=>$this->src->nationID,
+12
View File
@@ -37,13 +37,25 @@ class DummyGeneral extends General
} }
} }
public function setCrewType(?GameUnitDetail $crewType){
$this->crewType = $crewType;
}
public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{ {
//crewType에만 반응하자
if($this->crewType !== null){
return $this->crewType->getBattleInitSkillTriggerList($unit);
}
return new WarUnitTriggerCaller(); return new WarUnitTriggerCaller();
} }
public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{ {
//crewType에만 반응하자
if($this->crewType !== null){
return $this->crewType->getBattlePhaseSkillTriggerList($unit);
}
return new WarUnitTriggerCaller(); return new WarUnitTriggerCaller();
} }
@@ -0,0 +1,14 @@
<?php
namespace sammo\Enums;
enum GeneralAccessLogColumn: string {
case id = 'id';
case generalID = 'general_id';
case userID = 'user_id';
case lastRefresh = 'last_refresh';
case refresh = 'refresh'; //순간 갱신 횟수(00:00에 초기화)
case refreshTotal = 'refresh_total'; //누적 갱신 횟수
case refreshScore = 'refresh_score'; //순간 벌점(턴 시간에 초기화)
case refreshScoreTotal = 'refresh_score_total'; //누적 벌점(지속적으로 감소, refreshScoreTotal <= refreshTotal)
}
-7
View File
@@ -15,11 +15,6 @@ enum GeneralColumn: string{
case bornyear = 'bornyear'; case bornyear = 'bornyear';
case deadyear = 'deadyear'; case deadyear = 'deadyear';
case newmsg = 'newmsg'; case newmsg = 'newmsg';
case con = 'con';
case connect = 'connect';
case refresh = 'refresh';
case logcnt = 'logcnt';
case refcnt = 'refcnt';
case picture = 'picture'; case picture = 'picture';
case imgsvr = 'imgsvr'; case imgsvr = 'imgsvr';
case name = 'name'; case name = 'name';
@@ -58,8 +53,6 @@ enum GeneralColumn: string{
case recent_war = 'recent_war'; case recent_war = 'recent_war';
case makelimit = 'makelimit'; case makelimit = 'makelimit';
case killturn = 'killturn'; case killturn = 'killturn';
case lastconnect = 'lastconnect';
case lastrefresh = 'lastrefresh';
case ip = 'ip'; case ip = 'ip';
case block = 'block'; case block = 'block';
case dedlevel = 'dedlevel'; case dedlevel = 'dedlevel';
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace sammo\Enums;
// mergeQueryColumn, createGeneralObjListFromDB, createGeneralObjFromDB 호출시 column 특수 모드 지정
enum GeneralQueryMode: int
{
/** 장수 식별을 위한 최소한의 정보, logger 초기화 없음 */
case Core = 0;
/** 게임 내에서 필수 이벤트 처리를 위한 정보, iAction 제외 */
case Lite = 1;
/** 게임 내 모든 이벤트 처리를 위한 정보, iAction 제외 */
case FullWithoutIAction = 2;
/** 게임 내 모든 이벤트 처리를 위한 정보, iAction 포함 */
case Full = 3;
/** 접속 정보를 포함한 모든 정보 */
case FullWithAccessLog = 4;
}
+7
View File
@@ -0,0 +1,7 @@
<?php
namespace sammo\Enums;
enum GeneralStorKey: string{
case latestReadPrivateMsg = 'latestReadPrivateMsg';
case latestReadDiplomacyMsg = 'latestReadDiplomacyMsg';
}
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace sammo\Enums;
enum TableName: string {
case general = 'general';
case generalTurn = 'general_turn';
case generalAccessLog = 'general_access_log';
case userRecord = 'user_record';
case nation = 'nation';
case nationTurn = 'nation_turn';
case nationEnv = 'nation_env';
case board = 'board';
case comment = 'comment';
case city = 'city';
case troop = 'troop';
case plock = 'plock';
case message = 'message';
case rankData = 'rank_data';
case hall = 'hall';
case oldNations = 'ng_old_nations';
case oldGenerals = 'ng_old_generals';
case emperior = 'emperior';
case diplomacy = 'diplomacy';
case diplomaticNotes = 'ng_diplomacy';
case tournament = 'tournament';
case betting = 'ng_betting';
case vote = 'vote';
case voteComment = 'vote_comment';
case auction = 'ng_auction';
case auctionBid = 'ng_auction_bid';
case statistic = 'statistic';
case history = 'ng_history';
case worldHistory = 'world_history';
case generalRecord = 'general_record';
case event = 'event';
case storage = 'storage';
case selectNPCToken = 'select_npc_token';
case selectPool = 'select_pool';
case games = 'ng_games';
case reservedOpen = 'reserved_open';
}
+21 -6
View File
@@ -31,29 +31,44 @@ class InvaderEnding extends \sammo\Event\Action{
$logger = new ActionLogger(0, 0, $env['year'], $env['month']); $logger = new ActionLogger(0, 0, $env['year'], $env['month']);
$needStop = false;
$userWin = false;
$cityCnt = $db->queryFirstField('SELECT count(*) FROM city WHERE nation = 0'); $cityCnt = $db->queryFirstField('SELECT count(*) FROM city WHERE nation = 0');
if($cityCnt == 0){ if($cityCnt == 0){
$needStop = true;
$nationName = $db->queryFirstField('SELECT name FROM nation LIMIT 1');
if(!\str_starts_with($nationName, 'ⓞ')){
$userWin = true;
}
}
else if($cityCnt == count(CityConst::all())){
$needStop = true;
$userWin = false;
}
if(!$needStop){
return [__CLASS__, "On Event"];
}
if($userWin){
//천통 엔딩 //천통 엔딩
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>이민족을 모두 소탕했습니다!"); $logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>이민족을 모두 소탕했습니다!");
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>중원은 당분간 태평성대를 누릴 것입니다."); $logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>중원은 당분간 태평성대를 누릴 것입니다.");
} }
else if($cityCnt == count(CityConst::all())){ else {
//이민족 엔딩 //이민족 엔딩
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>중원은 이민족에 의해 혼란에 빠졌습니다."); $logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>중원은 이민족에 의해 혼란에 빠졌습니다.");
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>백성은 언젠가 영웅이 나타나길 기다립니다."); $logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>백성은 언젠가 영웅이 나타나길 기다립니다.");
} }
else{
return [__CLASS__, "On Event"];
}
$gameStor->setValue('isunited', 3); $gameStor->setValue('isunited', 3);
$logger->flush(); $logger->flush();
$gameStor->conlimit = $gameStor->conlimit * 100; $gameStor->refreshLimit = $gameStor->refreshLimit * 100;
$eventID = Util::array_get($env['currentEventID']); $eventID = Util::array_get($env['currentEventID']);
$db->delete('event', 'id = %i', $eventID); $db->delete('event', 'id = %i', $eventID);
return [__CLASS__, 'Deleted']; return [__CLASS__, 'Deleted'];
} }
} }
@@ -18,7 +18,7 @@ class MergeInheritPointRank extends \sammo\Event\Action
{ {
$db = DB::db(); $db = DB::db();
$generals = General::createGeneralObjListFromDB(null, null, 2); $generals = General::createGeneralObjListFromDB(null, null);
$points = new Map(); $points = new Map();
$points->allocate(count($generals)); $points->allocate(count($generals));
+2 -2
View File
@@ -88,7 +88,7 @@ class ProcessIncome extends \sammo\Event\Action
// 각 장수들에게 지급 // 각 장수들에게 지급
foreach ($generalRawList as $rawGeneral) { foreach ($generalRawList as $rawGeneral) {
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false); $generalObj = new General($rawGeneral, null, null, null, null, $year, $month, false);
$gold = Util::round(getBill($generalObj->getVar('dedication')) * $ratio); $gold = Util::round(getBill($generalObj->getVar('dedication')) * $ratio);
$generalObj->increaseVar('gold', $gold); $generalObj->increaseVar('gold', $gold);
@@ -169,7 +169,7 @@ class ProcessIncome extends \sammo\Event\Action
// 각 장수들에게 지급 // 각 장수들에게 지급
foreach ($generalRawList as $rawGeneral) { foreach ($generalRawList as $rawGeneral) {
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false); $generalObj = new General($rawGeneral, null, null, null, null, $year, $month, false);
$rice = Util::round(getBill($generalObj->getVar('dedication')) * $ratio); $rice = Util::round(getBill($generalObj->getVar('dedication')) * $ratio);
$generalObj->increaseVar('rice', $rice); $generalObj->increaseVar('rice', $rice);
@@ -41,7 +41,7 @@ class ProvideNPCTroopLeader extends \sammo\Event\Action
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) { foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
$nationID = $nation['nation']; $nationID = $nation['nation'];
$maxNPCTroopLeaderCnt = self::MaxNPCTroopLeaderCnt[$nation['level']]; $maxNPCTroopLeaderCnt = self::MaxNPCTroopLeaderCnt[$nation['level']] ?? 0;
$NPCTroopLeaderCnt = $NPCTroopLeaderCntByNation[$nationID] ?? 0; $NPCTroopLeaderCnt = $NPCTroopLeaderCntByNation[$nationID] ?? 0;
if ($NPCTroopLeaderCnt >= $maxNPCTroopLeaderCnt) { if ($NPCTroopLeaderCnt >= $maxNPCTroopLeaderCnt) {
+1 -1
View File
@@ -131,7 +131,7 @@ class RaiseDisaster extends \sammo\Event\Action
$generalList = array_map( $generalList = array_map(
function ($rawGeneral) use ($city, $year, $month) { function ($rawGeneral) use ($city, $year, $month) {
return new General($rawGeneral, null, $city, null, $year, $month, false); return new General($rawGeneral, null, null, $city, null, $year, $month, false);
}, },
$generalListByCity[$city['city']] ?? [] $generalListByCity[$city['city']] ?? []
); );
+31 -2
View File
@@ -12,6 +12,8 @@ use sammo\LiteHashDRBG;
use sammo\RandUtil; use sammo\RandUtil;
use sammo\Scenario\GeneralBuilder; use sammo\Scenario\GeneralBuilder;
use sammo\Scenario\Nation; use sammo\Scenario\Nation;
use sammo\ServerEnv;
use sammo\ServerTool;
use sammo\UniqueConst; use sammo\UniqueConst;
use sammo\Util; use sammo\Util;
@@ -93,6 +95,7 @@ class RaiseInvader extends \sammo\Event\Action
public function run(array $env) public function run(array $env)
{ {
$db = DB::db(); $db = DB::db();
$npcEachCount = $this->npcEachCount; $npcEachCount = $this->npcEachCount;
/** @var \sammo\CityInitDetail[] */ /** @var \sammo\CityInitDetail[] */
@@ -104,6 +107,16 @@ class RaiseInvader extends \sammo\Event\Action
$cities[] = $cityObj; $cities[] = $cityObj;
} }
if(!$cities){
return [__CLASS__, 0];
}
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->setValue('isunited', 1);
$turnterm = $gameStor->turnterm;
$generalCnt = $db->queryFirstField('SELECT count(*) FROM general');
if ($npcEachCount < 0) { if ($npcEachCount < 0) {
$npcEachCount = $npcEachCount =
$db->queryFirstField('SELECT count(no) from general where npc < 4') / count($cities); $db->queryFirstField('SELECT count(no) from general where npc < 4') / count($cities);
@@ -111,6 +124,19 @@ class RaiseInvader extends \sammo\Event\Action
} }
$npcEachCount = max(10, Util::toInt($npcEachCount)); $npcEachCount = max(10, Util::toInt($npcEachCount));
$totalGenerals = $npcEachCount * count($cities) + $generalCnt;
if ($totalGenerals > ServerEnv::$maxGeneralsPerMinute * $turnterm) {
foreach ([1, 2, 5, 10, 20, 30, 60, 120] as $nextTurnterm) {
if ($totalGenerals > ServerEnv::$maxGeneralsPerMinute * $nextTurnterm) {
continue;
}
ServerTool::changeServerTerm($nextTurnterm, true);
break;
}
}
$specAvg = $this->specAvg; $specAvg = $this->specAvg;
if ($specAvg < 0) { if ($specAvg < 0) {
$specAvg = $db->queryFirstField('SELECT avg((`leadership` + `strength` + `intel`)) from general where npc < 4'); $specAvg = $db->queryFirstField('SELECT avg((`leadership` + `strength` + `intel`)) from general where npc < 4');
@@ -140,6 +166,11 @@ class RaiseInvader extends \sammo\Event\Action
$month, $month,
))); )));
$db->update('nation', [
'war' => 0,
'scout' => 0,
], '1');
$disabledInvaderCity = $this->moveCapital($rng); $disabledInvaderCity = $this->moveCapital($rng);
$serverID = UniqueConst::$serverID; $serverID = UniqueConst::$serverID;
$existNations = $db->queryFirstColumn("SELECT nation FROM `nation`"); $existNations = $db->queryFirstColumn("SELECT nation FROM `nation`");
@@ -260,8 +291,6 @@ class RaiseInvader extends \sammo\Event\Action
'secu' => $db->sqleval('secu_max'), 'secu' => $db->sqleval('secu_max'),
], true); ], true);
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->setValue('isunited', 1);
refreshNationStaticInfo(); refreshNationStaticInfo();
$logger = new ActionLogger(0, 0, $year, $env['month']); $logger = new ActionLogger(0, 0, $year, $env['month']);
@@ -0,0 +1,226 @@
<?php
namespace sammo\Event\Action;
use sammo\ActionLogger;
use sammo\CityConst;
use sammo\DB;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\InheritanceKey;
use sammo\GameConst;
use sammo\General;
use sammo\JosaUtil;
use sammo\Json;
use sammo\KVStorage;
use sammo\LiteHashDRBG;
use sammo\RandUtil;
use sammo\UniqueConst;
use sammo\Util;
use function sammo\getNationChiefLevel;
use function sammo\getNationLevel;
use function sammo\giveRandomUniqueItem;
class UpdateNationLevel extends \sammo\Event\Action
{
public function run(array $env)
{
$db = DB::db();
$year = $env['year'];
$month = $env['month'];
$startYear = $env['startyear'];
$nationCityCounts = [];
foreach ($db->queryAllLists('SELECT nation, count(*) FROM city WHERE LEVEL>=4 GROUP BY nation') as [$nationID, $cityCnt]) {
$nationCityCounts[$nationID] = $cityCnt;
}
$nationLevelByCityCnt = [
0, //방랑군
1, //호족
2, //군벌
5, //주자사
8, //주목
11, //공
16, //왕
21, //황제
];
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
//TODO: level이 진관수이소중대특 체계를 벗어날 수 있음
$nationID = $nation['nation'];
$cityCnt = $nationCityCounts[$nationID] ?? 0;
/** @var int */
$nationlevel = 0;
foreach ($nationLevelByCityCnt as $cmpNationLevel => $cmpCityCnt) {
if ($cityCnt < $cmpCityCnt) {
break;
}
$nationlevel = $cmpNationLevel;
}
if ($nationlevel > $nation['level']) {
$levelDiff = $nationlevel - $nation['level'];
$oldLevel = $nation['level'];
$nation['level'] = $nationlevel;
$updateVals = [
'level' => $nationlevel,
'gold' => $db->sqleval('gold + %i', $nationlevel * 1000),
'rice' => $db->sqleval('rice + %i', $nationlevel * 1000),
];
$nationName = $nation['name'];
$lordName = $db->queryFirstField('SELECT name FROM general WHERE nation = %i AND officer_level = 12', $nationID);
$oldNationLevelText = getNationLevel($oldLevel);
$nationLevelText = getNationLevel($nationlevel);
$logger = new ActionLogger(0, $nationID, $year, $month, false);
$josaYi = JosaUtil::pick($lordName, '이');
switch ($nationlevel) {
case 7: //황제
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><D><b>{$nationName}</b></> {$oldNationLevelText} <Y>{$lordName}</>{$josaYi} <C>{$nationLevelText}</>{$josaRo} 옹립되었습니다.");
$logger->pushNationalHistoryLog("<D><b>{$nationName}</b></> {$oldNationLevelText} <Y>{$lordName}</>{$josaYi} <C>{$nationLevelText}</>{$josaRo} 옹립");
$auxVal = Json::decode($nation['aux']);
$auxVal['can_국기변경'] = 1;
$auxVal['can_국호변경'] = 1;
$updateVals['aux'] = Json::encode($auxVal);
break;
case 6: //왕
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 책봉되었습니다.");
$logger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 책봉");
break;
case 5: //공
case 4: //주목
case 3: //주자사
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 임명되었습니다.");
$logger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 임명됨");
break;
case 2: //군벌
$josaRa = JosaUtil::pick($nationName, '라');
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><Y>{$lordName}</>{$josaYi} 독립하여 <D><b>{$nationName}</b></>{$josaRa}는 <C>$nationLevelText</>{$josaRo} 나섰습니다.");
$logger->pushNationalHistoryLog("<Y>{$lordName}</>{$josaYi} 독립하여 <D><b>{$nationName}</b></>{$josaRa}는 <C>$nationLevelText</>{$josaRo} 나서다");
break;
}
$db->update('nation', $updateVals, 'nation=%i', $nation['nation']);
$logger->flush();
$turnRows = [];
foreach (Util::range(getNationChiefLevel($nation['level']), 12) as $chiefLevel) {
foreach (Util::range(GameConst::$maxChiefTurn) as $turnIdx) {
$turnRows[] = [
'nation_id' => $nation['nation'],
'officer_level' => $chiefLevel,
'turn_idx' => $turnIdx,
'action' => '휴식',
'arg' => null,
'brief' => '휴식'
];
}
}
$db->insertIgnore('nation_turn', $turnRows);
if ($levelDiff) {
//유니크 아이템 하나 돌리자
$targetKillTurn = $env['killturn'];
$targetKillTurn -= 24 * 60 / $env['turnterm'];
$nationGenIDList = $db->queryFirstColumn(
'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2',
$nation['nation'],
$targetKillTurn
);
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux']);
$chiefID = null;
$uniqueLotteryWeightList = [];
$relYear = $year - $startYear;
$maxTrialCountByYear = 1;
foreach (GameConst::$maxUniqueItemLimit as $tmpVals) {
[$targetYear, $targetTrialCnt] = $tmpVals;
if ($relYear < $targetYear) {
break;
}
$maxTrialCountByYear = $targetTrialCnt;
}
foreach ($nationGenList as $nationGen) {
if ($nationGen->getVar('officer_level') == 12) {
$chiefID = $nationGen->getID();
}
$trialCnt = min($maxTrialCountByYear, count(GameConst::$allItems));
foreach ($nationGen->getItems() as $item) {
if (!$item->isBuyable()) {
$trialCnt -= 1;
}
}
if ($trialCnt <= 0) {
continue;
}
$score = $nationGen->getVar('belong') + 10;
if ($nationGen->getVar('officer_level') == 12) {
$score += 60;
} else if ($nationGen->getVar('officer_level') == 11) {
$score += 30;
} else if ($nationGen->getVar('officer_level') > 4) {
$score += 15;
}
$score *= 2 ** $trialCnt;
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
}
$nationLevelUpRNG = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'nationLevelUp',
$year,
$month,
$nationID
)));
foreach (Util::range($levelDiff) as $idx) {
if (!$uniqueLotteryWeightList) {
break;
}
/** @var General */
$winnerObj = $nationLevelUpRNG->choiceUsingWeightPair($uniqueLotteryWeightList);
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
$givenUniqueRNG = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'givenUnique',
$year,
$month,
$nationID,
$winnerObj->getID(),
)));
giveRandomUniqueItem($givenUniqueRNG, $winnerObj, '작위보상');
$winnerObj->applyDB($db);
}
if ($chiefID) {
$chiefObj = General::createGeneralObjFromDB($chiefID, ['belong', 'npc', 'aux'], GeneralQueryMode::Lite);
$chiefObj->increaseInheritancePoint(InheritanceKey::unifier, 250 * $levelDiff);
$chiefObj->applyDB($db);
}
}
}
}
}
}

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