Compare commits

..
Author SHA1 Message Date
Jinhyun Kim fa4a266d77 misc: 개인 기록에 전략 수행 내역이 남도록 수정, 백성동원 대상 도시도 남도록 수정 2023-09-09 07:48:48 +09:00
Hide_D 32e854858e feat: 랜덤 턴 초기화 시간 범위를 상세하게 알려줌 2023-09-03 17:11:41 +00:00
Hide_D f13371e679 fix: 저격에서 raiseType을 저격시도/저격발동 일치 2023-08-17 10:25:04 +09:00
Hide_D 2420f594a6 game: 자동 출병 조건 일부 수정
- 국고 병령이 2000 밑이더라도, 유저장은 출병
2023-08-14 07:30:16 +00:00
Hide_D b7b0a1050c feat: 도시 함락 시 수비 장수에게 트리거 발동 2023-08-14 06:04:43 +00:00
Hide_D d2a90157b9 fix: 트래픽에서 접속자수가 제대로 집계되지 않는 문제 2023-08-13 07:26:09 +00:00
Hide_D a32cb3a2c0 fix: 수비X 관련 warning
- 버그는 있으나 의도대로는 작동하였음
2023-08-12 10:07:58 +00:00
Hide_D 7c0a3a6955 fix: 접속량 정보가 기록되지 않았음 2023-08-12 10:06:08 +00:00
Hide_D 7d2e2945a1 fix: 연감 한번 더 수정 2023-08-10 19:08:21 +09:00
Hide_D dc526c7359 fix: 연감 수정 2023-08-10 19:06:40 +09:00
Hide_D 6c4cb484da fix: 연감 1개월차 수정 2023-08-10 19:06:01 +09:00
Hide_D d41246de9d fix: 초기 시작시 연감이 안보임 2023-08-10 19:04:55 +09:00
Hide_D 6d40783224 fix: 수극으로 인한 저격 소모 2023-08-07 13:19:52 +00:00
Hide_D 6eb6014e80 game: 출병시 전멸시페이즈 증가 적용
- 마지막 페이즈가 아닐 때 전멸 시 페이즈 증가
2023-08-07 11:26:43 +00:00
Hide_D 103cf3f882 game: 파죽지세 시나리오에서 수비끔시 훈사영향없음 2023-08-07 11:24:17 +00:00
Hide_D 5969e0c82b fix: 수극이 다른 저격과 따로 동작 2023-08-05 10:12:34 +00:00
Hide_D 945f9027dd game: StrongAttacker의 보정을 공방40%씩으로
- 병종저격하면 동률
2023-08-05 09:10:17 +00:00
Hide_D 0bf3145042 game: 파죽지세 모드, 접경귀환 2023-08-05 09:01:54 +00:00
Hide_D 905669755f feat: 접경 귀환 기능 추가 2023-08-05 08:57:15 +00:00
Hide_D 57b12e8c04 fix: Session에서 로그인 정보를 세심히. 2023-08-05 08:47:45 +00:00
Hide_D eccd883edc feat: NotOccupiedCity constraint 2023-08-05 07:59:26 +00:00
Hide_D 895b134cd0 feat: InstantAction 개념 추가 2023-08-05 07:54:55 +00:00
Hide_D 7258573e4d misc: 닥공전 이름을 파죽지세로 변경 2023-08-05 07:20:12 +00:00
Hide_D cbdfa6f6fc feat: 닥공전 기능 추가
- 장수 상대로 공격자인 경우
  - 공, 방 50%씩
2023-08-05 07:15:36 +00:00
Hide_D ed25c58410 fix: 오타 수정 2023-08-05 07:14:40 +00:00
Hide_D 16cfa46864 feat: scenarioEffect 추가
- 모든 General에 iAction으로 작동
2023-08-05 06:53:19 +00:00
Hide_D e54a0a6668 feat: 시나리오 생성 시 에러가 발생하면 메시지를 띄움 2023-08-05 06:52:50 +00:00
Hide_D eb545724ea fix: 천통후 이벤트에서 유산 포인트를 얻을 수 있는 문제 수정 2023-08-05 05:19:40 +00:00
Hide_D 7858b48bad fix: b_betting 수정 2023-08-03 16:20:32 +00:00
Hide_D a4ed41edbe fix: mergeQueryColumn위치 수정 2023-08-03 14:19:23 +00:00
Hide_D b5a9e52c43 fix: 인사부는 GeneralLite가 아니라 General 필요
- 추방시 명성 깎이는 문제 때문
2023-08-03 13:35:55 +00:00
Hide_D c6166d3295 fix: 수뇌임명 안되는 버그 수정
- 아니 대체 왜 경고를 안 띄우는거야!
2023-08-03 13:32:37 +00:00
Hide_D 9520d29109 fix: General 생성 코드 수정 2023-08-03 13:31:30 +00:00
Hide_D 3edfff146e General 클래스를 General, GeneralLite로 분리 (#236)
내부 코드 사용례에서 General 테이블의 column을 일부만 가져오는 경우가 다수 있습니다.

다만 General 클래스에서 각종 iAction에 해당하는 트리거 함수 호출을 위해서는 모든 column을 다 가져와야 정상 동작이 가능한 만큼, iAction interface를 구현한 General 클래스와, 구현하지 않은 GeneralLite 클래스 둘로 나눕니다.

또한 General 클래스에서는 필요한 column을 다 가져오도록 변경합니다.

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/236
2023-08-03 21:32:01 +09:00
Hide_D 38416ccdf8 fix,refac: 잠재적인 버그 위치 수정
- aux가 null이 아니라 0으로 되고 있었음
- (0 == null) == true이니 그동안 되고는 있었겠으나..
- increaseInheritancePointRaw()를 호출하도록 변경
2023-08-01 16:24:55 +00:00
Hide_D eeb5eabd12 feat: increaseInheritancePoint에 더해진 후의 값 반환 2023-08-01 16:24:52 +00:00
Hide_D 41273f97db feat,refac: increaseInheritancePointRaw 추가
- ownerID만으로 처리 가능
2023-08-01 16:24:43 +00:00
Jinhyun KimandGitea 0e23677e1b Merge pull request 'fix: 징병 가능 여부 판별 시 상대 년도 판별 로직 오류 해결' (#233) from jyp9/core:relyearfix into devel 2023-07-29 14:57:59 +00:00
Hide_D 0f085c7f36 fix: zero-ref 2023-07-27 17:27:11 +00:00
Hide_D bd90076441 phan: update config.php 2023-07-27 17:27:08 +00:00
Hide_D 1801bdf55b fix: 설문조사 시 아이템 추첨 문제
-  tryUniqueItemLottery()는 itemObjs 배열을 요구
- itemObjs 배열은 GeneralQueryMode::Full 에서만 사용가능
- 즉, Lite여서는 안됨!
2023-07-21 13:26:26 +00:00
Hide_D f27f0edfb6 fix: 빙의시 경고 제거 2023-07-21 13:22:04 +00:00
Hide_D 02f23e7db4 fix: 토너먼트 경고 해제 2023-07-21 13:09:45 +00:00
Hide_D 9871e24811 fix: defaultEventColumn에 turntime 추가
- 많이 쓰일 것으로 예상
2023-07-18 11:05:07 +09:00
Hide_D a7dac2ce15 fix: mergeQueryColumn에서 query 계산 방식 변경
- 요청 쿼리 = queryMode + reqColumn로 변경
- 기존에는 null일 경우에만 queryMode 전체, null이 아니면 queryMode를 한 단계 낮추고,
   reqColumn을 더하는 형태였음
- 지난 버그에서 혼동을 일으키는 요소였으므로 수정
2023-07-18 10:54:36 +09:00
Hide_D ed1d2cbf0d Revert "fix: 발령에서 destGeneral에 turntime 필요"
This reverts commit 06ca32802b.
2023-07-18 10:49:37 +09:00
Hide_D 06ca32802b fix: 발령에서 destGeneral에 turntime 필요 2023-07-17 17:44:45 +00:00
Hide_D 568b45f93a fix: minimumColumn에 owner 필요 2023-07-17 17:43:32 +00:00
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
Hide_D bee4de377a feat: 버전 정보 페이지 추가 2023-03-22 23:09:53 +09:00
Hide_D b02911038b fix: 갱신시마다 커맨드 테이블을 다시 불러줘야 함 2023-03-22 22:58:05 +09:00
Hide_D 9b4d5455e5 feat: GetConst에서 버전 정보 반환 2023-03-22 22:54:47 +09:00
Hide_D ca3e64f3b9 feat: MenuItem에 funcCall 타입 추가후 처리 2023-03-22 22:44:42 +09:00
Hide_D 4d2b5ced82 feat: 메뉴 구성에 line 추가 2023-03-22 22:04:35 +09:00
Hide_D e385820301 fix: classMap에서 orig.php만 있고, 본 php는 없는 케이스 고려 2023-03-22 21:50:55 +09:00
Hide_D ec7c97d696 feat: hightlight btn, 토너먼트/베팅장 강조 2023-03-22 02:23:14 +09:00
Hide_D aae730d39c fix: gatewayButton 2023-03-21 01:51:39 +09:00
Hide_D 3c412f2803 fix: cr 시나리오 병종을 현재 버전에 맞게 수정 2023-03-21 01:44:27 +09:00
Hide_D 25769a9435 fix: sqlite3 db ignore 대상 추가 2023-03-21 01:42:25 +09:00
Hide_D 6c76d688b5 fix: 메시지 삭제 안되는 버그
- GetRecentMessage에서 keepRecent 관련 오동작 수정
  - 왜 이걸 넣었는지 생각해보기로..
2023-03-21 01:38:58 +09:00
Hide_D 790c58f2b6 feat: 메시지 빠른 답장 대상 지정 2023-03-20 02:12:57 +09:00
Hide_D 1eba863cc4 misc: 폰트 설정이 다르더라도 툴바 버튼 줄 수 유지 2023-03-20 01:13:21 +09:00
Hide_D fbe5739d82 feat: 메시지 응답시, 읽음 처리 2023-03-20 01:06:53 +09:00
Hide_D f8f8ef7dd3 misc: MainControlBar에 붙은 class 정리 2023-03-20 01:02:41 +09:00
Hide_D ecc375ef41 fix: customize scss에 맞게 다시 수정 2023-03-20 00:16:32 +09:00
Hide_D 9e17e58ecb dep: package update
- decl type 변경 포함
2023-03-20 00:02:04 +09:00
Hide_D 18f7e7b7c1 dep: package update 2023-03-19 23:12:09 +09:00
Hide_D b15b09cc1e dep: package update 2023-03-19 22:59:00 +09:00
Hide_D 49f2f85f79 dep: package-update 2023-03-19 17:45:17 +09:00
Hide_D 2245383d9e dep: remove bootstrap-vue-3 2023-03-19 17:17:45 +09:00
Hide_D e619a6b509 misc: 내무부에서 에디터 폼 최소 높이 높임 2023-03-19 16:59:13 +09:00
Hide_D fb9e750fe2 game: 외교권자가 아니면 외교 메시지 알림 없음 2023-03-19 16:51:06 +09:00
Hide_D 457aa0e4a5 misc: getNewMsgToast 힌트에 따라 수정 2023-03-19 15:38:49 +09:00
Hide_D 761b91b7db fix, refac: bvn에 맞게 tooltip directive 변경
- installVue3Component로 통합
- boostrap-vue-next 0.7.3 directive 문제 우회
2023-03-19 14:41:09 +09:00
Hide_D 31f4472a8a dep: upgrade bv3 bvn 2023-03-19 13:29:58 +09:00
Hide_D a79585f8de fix: 메시지 보러가기를 누르더라도 이미 읽음 처리를 해야함 2023-03-19 12:56:55 +09:00
Hide_D 69fbbbb51a feat: 개인/외교 메시지 수신시 버튼 추가 2023-03-19 12:54:53 +09:00
Hide_D 5eecbfc6f8 misc: package.json 요구로 임시 처리 2023-03-19 12:54:29 +09:00
Hide_D 9121780d82 feat: is1000pxMode에 widthMode 통합 2023-03-18 09:03:37 +09:00
Hide_D 6691aa3526 feat: PageFront에 토너먼트 베팅장 활성시 색 변경 2023-03-18 02:10:13 +09:00
Hide_D 582163ab46 fix: 부대장의 특기를 없앰.
- 특기 수령 년도를 999년으로 변경
2023-03-17 13:28:23 +09:00
Hide_D 394a70319f game: cr 시나리오에서 '척사'를 3등급 병종 문제로 제거 2023-03-17 02:18:23 +09:00
Hide_D 4d340abdcf feat: BaseAPI의 launch()에 타입 지정
- APIRecoveryType이 명시
2023-03-17 01:39:10 +09:00
Hide_D 6b9cfe46a0 feat: APIHelper에서 recovery 반환 타입 경로 추가 2023-03-17 01:18:20 +09:00
Hide_D 1d4707fb20 fix: recovery를 typescript API와 매칭 2023-03-17 01:16:55 +09:00
Hide_D d673024a10 feat: APIRecoveryType을 포함한 리턴 방법 2023-03-17 01:10:59 +09:00
Hide_D 3513aae088 fix: 지도 도시 민감도 문제 수정
- touchend는 touchmove와는 별개이므로 함께 처리
2023-03-17 00:30:22 +09:00
Hide_D 83c43d0261 fix: ProvideNPCTroopLeader 2023-03-16 23:59:24 +09:00
Hide_D 53cd8aeb5d fix: cr 시나리오에 선포가 없는 버그 수정 2023-03-16 19:27:28 +09:00
Hide_D 65b861d7ee fix: cr맵 배경 500px 2023-03-16 12:22:23 +09:00
Hide_D a5432e59d0 fix: CreateManyNPC 경고 제거 2023-03-16 03:49:19 +09:00
Hide_D e67b45e9cd game: 거울세계 구조 수정 2023-03-16 03:20:14 +09:00
Hide_D 8a8d9db7f9 game: 910 이벤트 시나리오 추가 수정
- 기본 이벤트 로직 오버라이드
  - 깃 끊김 없음
- 특수 커맨드(제한없는 건국, 인구이동, 맹훈련)
- 특수맵에 규모 적용
2023-03-16 01:24:06 +09:00
Hide_D 602cf3bf13 game: cr_건국,맹훈련,인구이동 추가
- 특수 맵 커맨드에 맞춤
- 건국: 소,중성 제한 없음
- 맹훈련: 훈련/사기진작의 2/3를 동시에
- 인구이동: 도시의 인구를 다른 곳으로 이동
2023-03-16 01:12:46 +09:00
Hide_D ab2e43e8dd fix: 국가가 하나도 없을 땐 CreateManyNPC가 동작하지 않아야 함 2023-03-16 00:07:04 +09:00
Hide_D 49b39c34eb fix: ProvideNPCTroopLeader는 국가가 없을땐 동작하지 않아야함 2023-03-16 00:04:33 +09:00
Hide_D fb5946fba5 feat: 소재 도시가 공백지여야하는 조건 작성 2023-03-15 23:19:01 +09:00
Hide_D 3ff4d51778 fix: 명령 선택시 지도의 배경이 안보이는 버그 수정 2023-03-15 04:11:50 +09:00
Hide_D 49d1bf4bad game: CR 맵 초기화 2023-03-15 03:48:37 +09:00
Hide_D 6a67a7de98 misc: 도시 렌더러에서 배경 클래스 지정 2023-03-15 02:11:47 +09:00
Hide_D f132d285e9 game: 랜덤임관 모드에서 초기 장수 제한 해제
- 사전 거병이 가능하므로, 시간에 따른 제한은 필요없을 것으로 판단
2023-03-15 01:15:10 +09:00
Hide_D f97b6e10d3 fix: 삼성 브라우저 다크모드 색상 틀어짐 수정 시도 2023-03-13 03:03:05 +09:00
Hide_D 90509516dd fix: Json::decode에서 빈줄은 array조차 아님 2023-03-13 02:44:58 +09:00
Hide_D 0a35505fa4 fix: 트래픽 일람에서 새 줄 파싱 문제 2023-03-13 02:43:44 +09:00
Hide_D 80a674436a fix: PageFront에서 부대 탑승여부가 보이지 않는 버그 2023-03-13 02:32:14 +09:00
Hide_D 50bf2a4614 fix: 도시 상인 % 표기 문제 수정 2023-03-13 00:00:01 +09:00
Hide_D 2f69be49e1 fix: 도시 정보에서 민심을 소수점 한자리로 제한 2023-03-12 18:48:50 +09:00
Hide_D 40fb8a4836 dep: lodash를 lodash-es 로 변경 2023-03-12 17:47:03 +09:00
Hide_D 0da9ffee9b fix: 일부 메인페이지 색상값을 옮겨오지 않은 버그 수정 2023-03-12 17:38:16 +09:00
Hide_D c88e3d1bfe fix: 메인, 사령부의 alert를 toast로 이동 2023-03-12 17:32:00 +09:00
Hide_D ae76ce0abd fix: PageFront 능력치 상승 기준이 엉뚱하게 잡혀있던 버그 수정 2023-03-12 17:17:53 +09:00
Hide_D d17b2518df 전역 하드코드 이벤트를 동적 변경 영역으로 이동 (#230)
기존에 작성해두었던 EventHandler 시스템으로 하드코드 이벤트 이동
- 매달
  - 보급선 설정
  - 전쟁 단기 수입 설정
  - 부대장 부여
- 1월
  - 유산 포인트 계산
  - 도시 인구 변화
  - 수입
  - 관직 제한 해제
  - 재난
  - 상인
  - 새해 알림
  - 특기 부여
- 4월
  - 관직 제한 해제
  - 재난
- 7월
  - 유산 포인트 계산
  - 도시 인구 변화
  - 수입
  - 관직 제한 해제
  - 재난
  - 상인
- 10월
  - 관직 제한 해제
  - 재난
- 천통 시
  - 유산 포인트 계산

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/230
2023-03-12 17:14:49 +09:00
Hide_D 4901a2d384 fix: 거병 시 인구 정보를 0이 아니라 null로 보내는 문제 수정 2023-03-12 16:38:32 +09:00
Hide_D 47bf5cdd17 misc: PageFront 로딩 직후에는 갱신 완료 메시지 없음 2023-03-09 20:32:10 +09:00
Hide_D 076c0cd604 fix: 메인 페이지 로그인, _119 페이지 링크 복구 2023-03-09 20:15:40 +09:00
Hide_D c4ccc451ec fix: 첫 건국 시 국가방침이 null임 2023-03-09 03:03:18 +09:00
Hide_D 3d9bb9c2e0 fix: index.php인경우 Session에 gameLogin 필요 2023-03-09 02:49:28 +09:00
Hide_D 4472cd0bdc fix: 가오픈 기간에 PageFront에 안오는 정보 수정 2023-03-09 02:48:21 +09:00
Hide_D efc36e223c misc: v_front -> index 2023-03-09 02:40:15 +09:00
Hide_D af2b82616f misc: index->old_index.php 2023-03-09 02:39:56 +09:00
Hide_D 6f5d7ff84b feat: Vue3로 새롭게 작성한 메인 페이지 (#229)
- v_front.php
- API 추가
  - General/GetFrontInfo
  - Global/GetGlobalMenu
- DTO 추가
  - MenuItem, MenuMulti, MenuSplit
- 글로벌 메뉴 출력 방식 변경
  - d_setting/GlobalMenu.php

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/229
2023-03-09 02:25:31 +09:00
Hide_D 4ba9468fae fix: 임시 토스트 본문 색상 변경 2023-03-09 02:18:04 +09:00
Hide_D 7905ddb7bf feat: scrollToSelector 2023-03-09 02:17:55 +09:00
Hide_D fdef4caa65 feat: 외부 호출이 불가능한 API 타입 정의 2023-03-09 02:17:41 +09:00
Hide_D ebaf63d541 feat: 10단위 column 분리 2023-03-09 02:17:00 +09:00
Hide_D 0e92973a05 fix: 누락된 메시지 def 수정 2023-03-09 02:16:05 +09:00
Hide_D 6a4fa8ee0d feat: Message 정의를 좀더 상세히 2023-03-09 02:15:42 +09:00
Hide_D 0081c86d1e fix: 국방 줄바꿈 수정 2023-03-05 00:09:59 +09:00
Hide_D 051fdee9b9 fix: MeekroDB에서 바뀐 설정 반영
- 설정하는 옵션이 기본값으로 변경
2023-03-04 14:16:14 +09:00
Hide_D 20330e19df fix: 불가침파기제의 warning 2023-03-01 12:43:30 +09:00
Hide_D bb5c9d8fd6 fix: CityConstBase warning 2023-03-01 12:38:45 +09:00
Hide_D 18ae530edf dep: php package update 2023-03-01 12:38:42 +09:00
Hide_D 294897df54 fix: Test 코드 변경 2023-03-01 12:38:33 +09:00
Hide_D 4fcafe88a7 fix: Session은 singleton이므로 생성자가 public이면 안됨 2023-03-01 04:33:13 +09:00
Hide_D 968e4afc8f fix: DummySession이 login 상태로 취급되지 않음 2023-03-01 04:29:37 +09:00
Hide_D 4193b884b0 fix: APIHelper DummySession 초기화 문제 2023-03-01 04:08:52 +09:00
Hide_D 9371de1b4a feat: PartialReservedCommand에 reloadCommandList 노출 2023-03-01 02:31:13 +09:00
Hide_D c5c7f96c1a feat, refac: 메인 페이지에서 커맨드 리스트를 동적으로 받아옴 2023-03-01 02:17:09 +09:00
Hide_D e721642a10 fix: timeout, retry 지정 2023-02-28 00:44:59 +09:00
Hide_D 4f0b18cc3c fix: DummySession, Session singleton 문제
- DummySession 호출 후 Session 호출시에도 DummySession이 나와야 함
- 함수 상속 관계 재 설정
2023-02-28 00:43:56 +09:00
Hide_D 904e26f56e fix: 토너먼트 자동개최모드 설정 관련 2023-02-24 20:02:58 +09:00
Hide_D 7a3642296a feat: 전투 시뮬레이터에 히든 버프 반영 가능 2023-02-24 00:25:29 +09:00
Hide_D 87e57aea0e feat: 전투 시뮬레이터에 시드 값 입력 가능
- 시드 값 입력시 반복 횟수는 1회로 고정
- 스킬 성공 여부는 동일하나, 실제 수치가 조금 다른 경우가 관측 이유는 추후 확인
- 히든 버프는 아직 미 반영
2023-02-23 23:48:09 +09:00
Hide_D ea256790ec game: 계략에서 도시 인구별 방어 계산식을 제곱근에서 로그로 변경
- (log(장수수 + 1, 2) - 1.25) * 0.04
- 8명까지는 기존 계산식과 큰 차이 없음
2023-02-23 22:59:10 +09:00
Hide_D 4cbd824ee0 fix: 초기 갱신 없이 국가 삭제시 버그 수정 2023-02-23 00:30:42 +09:00
Hide_D 4db1a4b32e fix: 접속자, 접속량 계산에 문제가 있던 부분 수정 2023-02-23 00:25:44 +09:00
Hide_D c060e05553 refac: 메시지 전달 j_ 코드를 API로 변경
- 메시지 전송
- 최근 메시지 수신
- 이전 메시지 수신
- 메시지 응답
- 연락처 수신
- 메시지 삭제
2023-02-22 01:29:00 +09:00
Hide_D 92cd195276 fix: 사령부 타 수뇌 텍스트 복사의 턴 순서도 수정 2023-02-21 02:32:18 +09:00
Hide_D f9b270fef3 fix: 텍스트 복사에서 턴 번호가 제대로 옮겨지지 않는 버그 수정 2023-02-21 02:29:23 +09:00
Hide_D 3f12dfd8ba feat: 턴 조작기에 '텍스트 복사' 추가 2023-02-21 02:26:52 +09:00
Hide_D d7e57f30eb fix: 사령부 복사하기 순서 지연 수정 시도 2023-02-21 02:04:03 +09:00
Hide_D ff822561cd game: 기병의 수비시 전투력 향상
- 기존 대비 전투력 5% 향상
2023-02-21 01:59:59 +09:00
Hide_D 273973f4b6 fix: Uri 기본 사용 방법 변경 2023-02-20 02:23:54 +09:00
Hide_D c648e2df85 fix: WebUtil Namespace 2023-02-20 01:27:52 +09:00
Hide_D 9b7e0ef169 fix, dep: 사용불가능한 phpuri를 league/uri로 대체
- 테스트 아직 없음
2023-02-20 01:02:18 +09:00
Hide_D 6eccd248ea dep: composer 2.5.4 2023-02-20 00:28:04 +09:00
Hide_D eaaa1c5da8 game: 초토화가 치안, 수비, 성벽도 낮추도록 변경 2023-02-05 15:59:33 +09:00
Hide_D 95776cda5c fix: 궁병이 아닌 경우에도 '맞 선제'가 정상 작동하도록 수정
- 궁병선제사격을 선제사격시도, 선제사격발동으로 분리
- 맞선제의 기준을 궁병이 아니라 '선제'의 활성화 여부로 구분
2023-01-28 03:09:44 +09:00
Hide_D 8ae0323dcc fix: 선제 사격에 저격을 쓰지 못하게 해야함 2023-01-28 02:56:35 +09:00
Hide_D f2d0020d92 fix: 피장파장은 피장파장을 대상으로 할 수 없음 2023-01-27 00:51:12 +09:00
Hide_D 67f3004eb0 fix: 이미 다른 부위에 입찰중인 경우 경매가 열리다 마는 버그 수정 2023-01-27 00:43:11 +09:00
Hide_D f933c0616b fix: 턴시간 고정이 0분만 가능한 버그 수정 2023-01-26 14:36:59 +09:00
Hide_D a240c6f901 game: 아시아 명장전(빙의전용) 생성 2023-01-02 20:05:07 +09:00
Hide_D e2c2ae0360 feat, refact: 메시지 응답 2022-12-05 01:55:38 +09:00
Hide_D bcd0117cdd misc: 메시지 삭제 API 정리 2022-12-05 01:42:54 +09:00
Hide_D 83f233cc99 feat, refac: 메시지 삭제 2022-12-05 01:40:12 +09:00
Hide_D 4f21eab7b1 feat, refact: 메시지 연락 리스트 수신 2022-12-05 01:10:41 +09:00
Hide_D 864ddf7efe feat, refac: 메시지 전송 2022-12-05 00:46:16 +09:00
Hide_D 9d3636cc49 misc: APIHelper에서 array가 반환된 경우 result: true 자동 삽입 2022-12-05 00:42:09 +09:00
Hide_D ce4f656030 fix: 정상 깃수 기준을 1 이상으로 변경 2022-12-02 00:43:43 +09:00
Hide_D a94f080cde fix: 미접속 유산 포인트 부여에서 '이벤트 깃수'를 카운트하는 버그 수정 2022-12-02 00:41:44 +09:00
Hide_D 71ca873c7a fix: msgOption은 null을 허용해야함. 2022-12-02 00:23:07 +09:00
Hide_D 6e0d13e1fb fix: 장수 생성시 보너스 스탯 표기 오류 2022-12-01 22:24:09 +09:00
Hide_D 059c4d999a game: 맞 선제시 이전 패치에서 변경된 전투력 반영 2022-12-01 01:13:43 +09:00
Hide_D f52e357e8a fix: 디버그용 코드 수정 2022-12-01 01:02:13 +09:00
Hide_D 761496be5c game: 정란, 벽력에 선제사격 추가, 벽력 공격력 약화
- 6페이즈 전투 기준으론 공격력 유지
- 벽력기준 돌격, 수비전 등에서 상대적 약화
2022-12-01 01:00:30 +09:00
Hide_D 551972d876 feat, refac: 오래된 메시지 불러오기 2022-11-30 01:32:17 +09:00
Hide_D 81c2fc4d43 game: 궁병의 선제 사격을 일반 공격력의 50%에서 2/3로 변경 2022-11-30 00:14:24 +09:00
Hide_D 3e542fcbfa game: 궁기병의 보병 상성 상향 수준 억제
- 공격력: 12.5% 향상
- 방어력: 9.1% 향상
2022-11-30 00:10:44 +09:00
Hide_D c9ab2c593d game: 궁기병의 보병 상대 전투력 향상
- 공격력 25% 향상 (20% 열세)
- 방어력 20% 향상 (25% 열세)
2022-11-30 00:07:46 +09:00
Hide_D 0c9e00e90a game: 목우의 수비 상성 약화
- 1.2(초기) -> 0.8(무상성) -> 1(현재)
- 25% 아군 피해 증가
2022-11-30 00:04:24 +09:00
Hide_D ea17972478 fix: 제거한 troop.ts 파일 빌드 수정 2022-11-29 02:13:43 +09:00
Hide_D 3d40df9755 feat, refac: 최근 메시지 API 2022-11-29 02:06:57 +09:00
Hide_D b4ac348645 Refac: 메시지 타입 지정으로 MessageType Enum 사용 2022-11-29 01:53:55 +09:00
Hide_D 374611f66c refac: MessageType enum 2022-11-29 01:49:19 +09:00
Hide_D 39b66fd626 misc: 사용되지 않는 구버전 부대편성 코드 제거 2022-11-28 23:51:21 +09:00
Hide_D 75dca322b4 fix: UserID가 null인 경우 대응 2022-11-10 17:14:21 +09:00
Hide_D cfdae1ddfa misc: 관리를 위해 mkdir에 group permission 부여 2022-11-05 15:17:57 +09:00
Hide_D 054a6c7073 feat: 모든 API를 기록하는 시스템
- sqlite3에 기록
- 느려지지 않기를...
2022-11-05 15:00:13 +09:00
Hide_D e93d9e6cf5 feat: API에서 민감한 argument 지정 2022-11-05 14:59:52 +09:00
Hide_D 30d99c6fc3 fix: DummySession에서 get이 잘못됨. 2022-11-05 14:58:22 +09:00
Hide_D 56c9b44c93 game: 이벤트 유니크 분실 메시지를 흥미롭게 변경 2022-11-02 21:17:04 +09:00
Hide_D 919ae5a863 game: 무작위 세계 이벤트 시나리오 가오픈 재생성 주기 단축 2022-11-01 23:00:59 +09:00
Hide_D 43b8e546f6 feat: 시나리오 별 사전 생성 시 재 생성 주기 결정 가능 2022-11-01 23:00:25 +09:00
Hide_D b90aef662b game: 무작위 세계 시나리오 초기 등록 2022-10-30 22:13:39 +09:00
Hide_D 1da47863ae feat: 전역 아이템 망실 이벤트 추가 2022-10-30 22:13:25 +09:00
Hide_D 81bd5c1914 feat: 무작위건국, 무작위수도이전 커맨드 추가 2022-10-30 21:47:24 +09:00
Hide_D b14f9a638f fix: 무작위장수명 모드에서 장수명이 제대로 지정되지 않음 2022-10-30 21:41:12 +09:00
Hide_D 8ff3a5a7a8 feat: GameConst에서 유니크 획득 확률 조정 가능 2022-10-30 21:29:48 +09:00
Hide_D 48c77bd6a2 feat: 장수명 무작위 생성 모드 가능 2022-10-30 15:16:40 +09:00
35a017c1dc fix: 천통 후 서버시드 출력 시 괄호를 열지 않고 닫았던 문제 수정 (#227)
Co-authored-by: Jinhyun Kim <lewha0@gmail.com>
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/227
Reviewed-by: Hide_D <hided62@gmail.com>
Co-authored-by: lewha0 <lewha0@noreply.storage.hided.net>
Co-committed-by: lewha0 <lewha0@noreply.storage.hided.net>
2022-10-10 03:29:48 +09:00
Hide_D a3e8a10da9 game: 건국 시점 유산 포인트 베팅 제공량 상향 2022-10-10 01:39:42 +09:00
Hide_D 142b96836e refac: 신규/복귀 유저 유산 포인트 지급 로직을 조금더 최적화 2022-10-05 00:26:04 +09:00
Hide_D 9be0d2ec2d refac: storeOldGeneral을 General::kill로 이동 2022-10-04 20:38:18 +09:00
Hide_D fd817650e7 fix: 지급 버그 수정 2022-10-04 11:32:52 +09:00
Hide_D 3c6cb96a9b feat: 신규/복귀 유저에게 장수 생성 시 유산 포인트 제공
- 이벤트 깃수 제외 500포인트
- 8기까지 적립
2022-10-04 11:25:40 +09:00
Hide_D c4537454f9 fix: 최대 임관년도 수 계산 버그 재 수정 2022-10-04 10:02:39 +09:00
Hide_D 82cdaa433e fix: 최대 임관년도 수 계산 버그 2022-10-04 01:07:11 +09:00
Hide_D 32dd3ff43f misc: AI에서 삭턴NPC 구분 기준을 1턴 추가 2022-10-04 00:13:52 +09:00
Hide_D 6a5840faaa fix: AI 후방 발령 누락분 수정 2022-10-03 23:38:53 +09:00
Hide_D 5b0a3b064d fix: AI 후방 발령 로직 버그 수정
- 징병시 인구 소모가 없는 경우 후방 발령 제외
- NPC 수뇌일때와 유저 수뇌일 때 도시 인구 계산식 다른 버그 수정
2022-10-03 23:37:07 +09:00
Hide_D 14b8bb9790 fix: 2번 연속 멸망 시 유산 포인트 계산 오류 2022-10-03 11:32:22 +09:00
Hide_D 650f4a5903 fix: 구조상 베팅 당첨 포인트는 은퇴시 반영되어야 함 2022-10-03 00:37:18 +09:00
Hide_D c50410a6da game: 은퇴시 토너먼트 보정치를 100%로
- 실수였음!
2022-10-02 23:27:41 +09:00
Hide_D b2a676cd8b game: 옥란백용구 향상 최대 30% -> 50% 2022-10-02 23:25:00 +09:00
Hide_D 50a75e4543 refac, game: 은퇴 시 포인트 반영 방식 변경
- 반영하지 않고 은퇴 이후로 넘기는 포인트 추가
- 은퇴시 계수를 Obj로 이동
2022-10-02 19:41:38 +09:00
Hide_D 22172ac66f fix: null coalesing 수정 2022-10-02 19:39:35 +09:00
Hide_D 392aaa343d fix: calcGenType을 updateInstance()로 이동 2022-10-02 19:36:17 +09:00
Hide_D d924f47d58 fix: warning 발생 제거 2022-10-02 19:35:05 +09:00
Hide_D 3b70cbe724 fix: GeneralAI env 설정 관련 버그 수정 2022-10-02 17:46:20 +09:00
Hide_D 5c3233f883 misc: 서버 리셋 페이지에서 기본 설정값 변경
- 자율 행동 전부 선택
- 자율 행동 기본 시간 24시간
- 사실모드: 가상
2022-10-02 17:43:40 +09:00
Hide_D b570bfa9d4 fix: NPC선전포고, 긴급포상에서 내부 NPC 국가 상태를 업데이트하도록 수정 2022-10-02 17:37:40 +09:00
Hide_D 270cb25285 refac: GeneralAI에서 상태를 추가 업데이트할 수 있도록 구조 변경 2022-10-02 17:33:23 +09:00
Hide_D 7d3b0db924 game: 계략 성공률을 5%p 하향
- 계략 성공률에 인구수를 반영하기 이전과 비교하여 1명있을 때에는 동일
- 한명도 없을때는 5%p 상승
- 두명 이상일 때에는 이전 대비 성공률 하향
2022-10-02 15:59:30 +09:00
Hide_D 74d310e113 fix: 불가침에서 '까지'는 해당 월을 포함하여야 함 2022-10-02 15:55:31 +09:00
Hide_D 45afb1c090 fix: 수동 은퇴 시 명예의전당에 등록되지 않는 버그 2022-09-27 10:00:44 +09:00
Hide_D 40fc2f8bbf fix: NPC 순간이동이 보급이 끊긴 도시에도 갈 수 있는 버그 수정 2022-09-24 22:29:58 +09:00
Hide_D a9de5a92e1 build: pre-commit에 lint 제거 2022-09-24 20:58:56 +09:00
Hide_D c592b00c3f game: 피장파장에 추가되었던 글로벌 전략 1턴 제거 2022-09-24 20:57:44 +09:00
Hide_D 2c81be4d12 game: 계략 방어 확률에 도시 거주 장수 수 반영
- sqrt(장수 수) * 5%p
2022-09-23 21:59:51 +09:00
Hide_D f10289f7b6 game: 피장파장은 이제 전략
- 글로벌 쿨 1턴
- 피장파장 쿨 8턴
2022-09-23 21:56:15 +09:00
Hide_D c1f06b4ce5 fix: 최대 임관 년도 수 제어 규약 우회 2022-09-22 11:54:47 +09:00
Hide_D 9ad3dbba90 game: 배신 관련 최종 수정, 20%부터, +10%p씩
- 공지 추가
2022-09-21 23:25:20 +09:00
Hide_D 12c62f87f7 game: 초기 배신 수치 추가 보정
- 배신 수치를 '2'로 변경.
- 명성 패널티를 30%로 시작해서 45%, 60%
2022-09-21 23:16:29 +09:00
Hide_D 635f1ae077 feat, game: 초반 '배신 수치' 1 증가, 배신 패널티 증가
- 184년 1월부터 배신수치 1 증가.
- 배신 패널티 당 15%, 최대 6회
2022-09-21 23:12:56 +09:00
Hide_D c89bd2f63f fix: 하야, 망명 시 최대 임관 년수가 반영되지 않는 버그 수정 2022-09-21 22:48:55 +09:00
Hide_D 2f94a8a2ca fix: 가오픈 기간 중 사망 메시지에서 조사가 중복되어 나오던 문제 수정 (#226)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/226
Reviewed-by: Hide_D <hided62@gmail.com>
2022-09-14 12:07:08 +09:00
Jinhyun Kim 85b0d35af0 fix: 가오픈 기간 중 사망 메시지에서 조사가 중복되어 나오던 문제 수정 2022-09-14 11:42:19 +09:00
Hide_D b25acacb1e fix: 징병 특기에 '비용 감소' 제거 누락 2022-09-10 19:04:46 +09:00
Hide_D c05a43f3b1 fix(oauth): 이메일 변경 시 oauthID를 받아오지 못하는 분기 수정 2022-09-09 03:28:18 +09:00
Hide_D d99976daa9 fix(oauth): 카카오로그인에서 이메일만 바뀐 경우 이메일 갱신 2022-09-09 03:11:34 +09:00
Hide_D 62f53d09bf feat, game: 징병 전특 리밸런싱, 징병/소집해제시 인구 변동 트리거 설정 2022-09-06 19:48:52 +09:00
Hide_D 88c78ec892 game, misc: 작위 상승 메시지 변경 2022-09-01 02:49:20 +09:00
Hide_D 006ca76922 refac: ExecuteEngine 반환 타입 변경 2022-08-30 22:51:14 +09:00
Hide_D 8cb2e2a447 fix: OAuth Redirect UTI가 사전 값과 다른 경우 domain 보정 2022-08-28 18:00:53 +09:00
Hide_D 517c85d003 misc: oauth.php 에러 상세 표기 2022-08-28 17:37:55 +09:00
Hide_D 83556b710c fix, feat: HTTP_HOST가 다른 경우에도 oauth redirect 허용
- oauth 대상에서 redirect 허용 host를 설정해야함.
2022-08-28 17:24:25 +09:00
Hide_D a43b9091f8 feat: WebUtil::replaceDomain 2022-08-28 17:21:37 +09:00
Hide_D e83a1bef49 fix, misc: 사이시옷 수정 2022-08-28 15:45:44 +09:00
Hide_D 1147a8262c fix: 아이템 이름 오기 2022-08-28 15:41:50 +09:00
Hide_D 8a987cc55e fix: 조사 관련 문제 수정 2022-08-28 15:40:52 +09:00
Hide_D b28ca864f9 dep: package update 2022-08-28 15:30:35 +09:00
Hide_D 4bf77a5c55 game: 궁병 공격 시도, 추가페이즈 선제 공격
- 수비 선제와 구조적으로 동일
- 첫번째 상대에게 선제 사격
- 궁병과 궁병의 대결인 경우 항상 맞 선제 사격
2022-08-28 14:35:14 +09:00
Hide_D 4ebc20f182 game: 전투 첫 페이즈 계략시도 보정은 무장 제외 2022-08-28 14:17:09 +09:00
Hide_D 9eff1ccaed fix: 경매장 이름 풀 난수 생성기에 seed 초기화값 문제 수정 2022-08-27 12:15:12 +09:00
Hide_D 66170c98dd game: 수비 끔 시 사기 감소량 -3 => -6 2022-08-27 03:00:16 +09:00
Hide_D 397c054c66 game: 유니크 경매 제한 시간 감소
- 1분턴 마감시간 기준 1시간 -> 30분
2022-08-27 02:57:01 +09:00
Hide_D 0611551dc0 game: 의병모집 생성량 변경
- 3 + 연감 기준 평균 장수수 / 8 (반올림)
- 국가별 장수수가 평균 80명부터 역전
2022-08-27 02:46:44 +09:00
Hide_D 008f88d995 game: 전투시 얻는 기술량에서 공격자 상향
- 공격자 기술: 공격자가 입은 피해 * 0.012 (구 0.01)
- 수비자 기술: 수비자가 입은 피해 * 0.009 (구 0.01)
2022-08-27 02:39:47 +09:00
Hide_D 7fe450bc07 Revert "revert: LazyVarUpdater에 \BackedEnum 롤백"
This reverts commit a88ec71b44.
2022-08-26 22:16:06 +09:00
Hide_D a88ec71b44 revert: LazyVarUpdater에 \BackedEnum 롤백 2022-08-26 17:30:24 +09:00
Hide_D 8a5a3b67f7 refac: utilGame/getNPCColor 2022-08-26 01:06:43 +09:00
Hide_D 63771da876 misc: utilGame/index.ts 2022-08-26 00:34:56 +09:00
Hide_D 68891fafdb misc: CityColumn enum 2022-08-26 00:34:45 +09:00
Hide_D df31300a0b refac: GeneralBasicCard의 부대장 요구 정보를 간소화 2022-08-26 00:34:42 +09:00
Hide_D 16fb782bbf refac: LazyVarUpdater의 key로 BackedEnum 허용 2022-08-26 00:34:39 +09:00
Hide_D ed3e013a53 misc: GeneralColumn enum 추가 2022-08-26 00:34:32 +09:00
Hide_D 0bf568a655 feat: 국방 설정 시, 작성자와 작성 일시를 기록 2022-08-26 00:34:15 +09:00
Hide_D a5e481af96 fix: utilGame format에서 한단계 다르게 차이나는 버그 수정 2022-08-21 18:53:55 +09:00
Hide_D 78a9641c14 dep: lodash -> lodash-es 2022-08-21 18:14:36 +09:00
Hide_D b517000650 game: 성벽 공격 시 소모 쌀 20% 감소 2022-08-21 17:52:25 +09:00
Hide_D 1d20eb3c3e game: 초반 M장 생성 시 무지장 대량 생성 2022-08-21 17:42:33 +09:00
Hide_D 8248ccbcd5 game: 시간이 지남에 따라 성벽 강화
- 183년 기준 동일.
- 220년 기준 40% 전투력 상승
2022-08-20 15:03:58 +09:00
Hide_D b880b9bace game: NPC가 조금 더 상위병종을 시도할 확률을 높임 2022-08-20 14:39:51 +09:00
Hide_D 2da374410b game: 필살 계수 향상 방식 너프 2022-08-20 14:29:54 +09:00
Hide_D fff8f9493b game: 유니크 아이템 경매 시 현재가보다 1% 더 높아야 함 2022-08-20 14:15:49 +09:00
Hide_D 987baaa307 misc: 아시아 명장전 장수 구성 수정 2022-08-19 21:11:02 +09:00
Hide_D 9512ea9b52 feat: APICoveryType에 맞게 InvalidResponse 확장 2022-08-18 01:08:38 +09:00
Hide_D b0f3c1c97d feat: APIRecoveryType Enum 생성 2022-08-18 01:08:35 +09:00
Hide_D e823b97cf2 fix: 세션 관리 api 에러 2022-08-18 01:08:28 +09:00
Hide_D 203859ee5f dep: denque 추가 2022-08-16 23:58:21 +09:00
Hide_D 4870e2fa30 feat: GetRecentRecord 추가
- 메인페이지 최신 로그
2022-08-16 23:57:47 +09:00
Hide_D 970b702a2b fix: 빙의장은 제대로 유산을 받지 못하는 버그 수정 2022-08-13 03:18:31 +09:00
Hide_D 053288b227 fix: applyDB시 rankVarRead 처리 오류 (=은퇴 버그 수정)
- 은퇴는 applyDB 이후에 실행됨
- applyDB 코드 오류로 이후 key값 문제로 은퇴가 실행되지 않음
2022-08-13 03:12:09 +09:00
Hide_D e9b975bea7 fix: 의병모집에서 명성, 계급이 설정되지 않는 버그 수정 2022-08-12 02:25:12 +09:00
Hide_D 89fda44db8 game: 목우 상향, 무상성화 2022-08-10 23:53:19 +09:00
Hide_D fac8536095 fix: 도시 비중 계산식에서 '종사' 누락 2022-08-09 02:04:39 +09:00
Hide_D c79e65b6b7 misc: 아시아 명장전 유저장 스탯 수정 2022-08-08 21:38:02 +09:00
Hide_D 677e65ff6d dep: npm package update 2022-08-06 20:26:35 +09:00
Hide_D 0c7589d524 fix,misc: phan 검사 수준 복구 2022-08-05 23:45:31 +09:00
Hide_D da27ae2bad dep,refac: DTO를 composer 외부로 이동 2022-08-05 23:43:38 +09:00
Hide_D f8cd58bcb3 refac: conv_general_stat을 xlrd대신 opnepyxl로 변경
- 국가명 - 수뇌는 아직 테스트 안 해 보았음...
2022-08-03 00:53:41 +09:00
sarsandHide_D 3671a289b8 아시아 명장전 시나리오(비급) 추가 (#225)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/225
Reviewed-by: Hide_D <hided62@gmail.com>
Co-authored-by: sars <sarsntony@gmail.com>
Co-committed-by: sars <sarsntony@gmail.com>
2022-08-02 16:47:41 +09:00
Hide_D 48f4dbec50 misc: 부대편성 1000px 버튼의 위치를 명확히 2022-07-31 22:34:33 +09:00
Hide_D bdb29006e9 refac: 부대편성에서 1000px 모드 버튼을 좌하단으로 2022-07-31 22:20:29 +09:00
Hide_D 5ea324f103 fix: v-b-tooltip에서 undefined -> string type 초기화 생략 2022-07-31 20:34:18 +09:00
Hide_D 2f0cd32c18 fix: 부대 편성에서 부대장 집합 순서로 정렬 필요 2022-07-31 19:50:52 +09:00
Hide_D e8911d40df fix: 부대 편성에서 부대장과 다른 도시 표기가 안됨 2022-07-31 12:08:40 +09:00
Hide_D 89f173e7e3 fix: 베팅 최소 한도가 10이 아니라 1로 된 버그 수정 2022-07-30 21:13:00 +09:00
Hide_D b0ab3f6ace fix: css 누락, 로딩 누락 2022-07-30 20:48:31 +09:00
Hide_D 641af435d4 fix: 리셋 페이지 css 2022-07-30 20:45:27 +09:00
Hide_D 16a2f20af0 fix: 장수 카드에서 '남은 시간'이 제대로 표기 안됨 2022-07-30 20:16:08 +09:00
Hide_D 79734a6dcf fix: 부대명 변경이 아무에게나 보임 2022-07-30 19:44:30 +09:00
Hide_D 2e2ff1b150 feat: 감찰부에서 '이전', '다음' 버튼 2022-07-30 19:34:34 +09:00
Hide_D 5ce899ee6e fix: 장수 카드에 부상스탯 미반영 2022-07-30 14:25:23 +09:00
Hide_D e041080773 fix: 유산 포인트가 0이어도 동작 2022-07-30 12:15:07 +09:00
Hide_D f8448fbb51 fix: 자동 해산에 필요한 변수를 제공하지 않음 2022-07-30 10:34:40 +09:00
Hide_D 8defcd29a4 fix: 인자 오류 수정 2022-07-30 10:31:31 +09:00
Hide_D fba60df9d1 fix: binarysearch 상한 에러 2022-07-29 01:24:09 +09:00
Hide_D a4ff1f44ba build: source-map 활성화(디버그용) 2022-07-29 01:13:51 +09:00
Hide_D 7b75f4e01b misc: GeneralLiteCard grid 조정 2022-07-27 23:02:35 +09:00
Hide_D a9fc69e70f game: 벽력거 비용 약 상승, 목우 비용 하향 2022-07-27 22:52:02 +09:00
Hide_D a06c574327 fix: non vue page css 누락 2022-07-27 22:37:27 +09:00
Hide_D 420ae2f45b fix: 동일 부위 제한일 때, 무한히 알림오는 버그
- 의도대로라면 1턴마다 한번씩이어야함
2022-07-27 22:33:12 +09:00
Hide_D 850073a096 game: 유니크 낙찰 시 연장될 때 '상인' 전환
- 개최자와 낙찰자가 다를때에만
2022-07-27 22:30:22 +09:00
Hide_D e40aa88253 misc: 유니크 경매장에서 아이템 효과 툴팁 2022-07-27 22:21:25 +09:00
Hide_D ff92b0149a game: 벽력거 방어력 약 하향 2022-07-27 22:08:12 +09:00
Hide_D e6049a17a2 fix: 강행이 훈련,사기가 떨어지지 않는 문제 2022-07-27 21:59:29 +09:00
Hide_D 9bc1bc13f2 fix: 누락된 토너먼트 css 2022-07-27 21:57:58 +09:00
Hide_D b9cda08a4e fix: 천하통일 후에는 유산 포인트 사용 방지 2022-07-27 21:54:49 +09:00
Hide_D 4e2193fe6f fix: 불가침 파기시 header 수정 2022-07-27 21:49:45 +09:00
Hide_D 155af45378 refac: bootstrap.scss 분리 후 별도 빌드 2022-07-27 21:44:24 +09:00
Hide_D 66d6bbc772 feat: 경량 base.scss 2022-07-27 20:53:44 +09:00
Hide_D 066a6d4e6a build: bootstrap.scss 분리 2022-07-27 20:48:43 +09:00
Hide_D 94f5834b61 fix: 시나리오 생성시 성격에 class prefix 없음 2022-07-27 19:44:05 +09:00
Hide_D 947286bd09 game: npc 징병 쌀 기준 낮춤 2022-07-27 18:48:37 +09:00
Hide_D a0dee353b5 feat: 새 부대편성 페이지 (#223)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/223
2022-07-27 18:01:41 +09:00
Hide_D 308b1f2348 fix: 감찰부 장수 변경시 tooltip 빈칸 버그 2022-07-26 23:56:50 +09:00
Hide_D 897780cf1c dep: package update 2022-07-26 23:32:43 +09:00
Hide_D 0f8a8011be fix: 중복되는 WarUnitTrigger의 priority 정정 2022-07-25 00:29:20 +09:00
Hide_D 7ebfd960b1 fix: 도시 관직 수치 조회 권한이 잘못됨 2022-07-24 17:23:20 +09:00
Hide_D 7b3d64996d fix: 감찰부 도시 관직명 누락 2022-07-24 17:15:06 +09:00
Hide_D e578a2f310 fix: 아이템 경매 버그 수정 2022-07-19 21:24:55 +09:00
Hide_D eecb4f699b game: 이미 같은 부위에 다른 유니크가 있는 경우, 경매 진행 방지 2022-07-17 22:34:05 +09:00
Hide_D 9f4f7a759e fix: 원조를 같은 국가로 지정할 수 있는 버그 수정 2022-07-17 16:40:40 +09:00
Hide_D 11a98eb184 fix: 장수 카드 부대 집합지가 항상 주황색 2022-07-17 16:40:35 +09:00
Hide_D ed0bc5e19f fix,refac: Nation/GetGeneralList에서 부대정보는 공개되어야 함 2022-07-17 01:37:07 +09:00
Hide_D 020a2d2668 fix: 감찰부 표기(*), 이름순 정렬 2022-07-16 16:39:12 +09:00
Hide_D 27cdd3ee4b misc: 구 감찰부 제거 2022-07-16 15:56:39 +09:00
Hide_D 43a95979e1 refac: 감찰부 vue3 재 작성 (#222)
- 장수 정보, 추가 정보 vue3 component
- b_battleCenter -> v_battleCenter

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/222
2022-07-16 15:49:23 +09:00
Hide_D 800106f9cb fix: 등용 버그 수정 시도 2022-07-14 11:40:30 +09:00
Hide_D e5c50e48d3 refac: defineComponent => vue3 setup 2022-07-13 22:37:37 +09:00
Hide_D 08e43bed71 fix: 서버 오픈 첫 턴에는 해산 불가 2022-07-13 22:07:25 +09:00
Hide_D 6773b8cddb fix: dependency 변경에 따른 오류 수정 2022-07-13 01:17:46 +09:00
Hide_D 23c030fd00 dep: package update 2022-07-12 21:47:01 +09:00
Hide_D d5e67bb16d refac: defineComponent => vue3 setup 2022-07-12 01:48:59 +09:00
Hide_D 188e3a0fa6 refac: defindComponent => vue3 setup 2022-07-12 01:26:33 +09:00
Hide_D b31ee022af refac: defineComponent => vue3 setup 2022-07-12 00:28:08 +09:00
Hide_D 87e063e03e fix,refac: 회의실에서 줄 바꿈이 표기 안되는 버그 수정 2022-07-12 00:09:58 +09:00
Hide_D 48fe26e4b1 refac: 숫자 입력기 재작성
- 입력마다 min, max clamp 작업 취소
2022-07-11 21:55:26 +09:00
Hide_D 88fcc64537 game: NPC 요양 기준 설정 가능 2022-07-11 20:23:55 +09:00
Hide_D d9beabbbbc feat: 발령시 장수 목록에 부대장 추가 표기 2022-07-10 21:58:30 +09:00
Hide_D 3da0a7d950 feat: 부대장인 경우 부대이름으로 검색 가능 2022-07-10 21:52:54 +09:00
Hide_D 50b1db75f0 fix: 본인이 아닌 수뇌자리에도 부대장 발령 표기 2022-07-10 21:27:34 +09:00
Hide_D 94bb96d208 feat: 부대장 발령 시 부대장 대신 부대 이름 표기 2022-07-10 20:50:33 +09:00
Hide_D 93490276fd misc: 집합에서 불필요한 조사 제거 2022-07-10 17:12:12 +09:00
Hide_D 73a7bf5a61 fix: 내정 도구 유니크가 동작하지 않는 버그 수정 2022-07-09 23:09:09 +09:00
Hide_D 8a1f8f8e2c fix: JsonString이 string->int auto casting하는 버그 수정 2022-07-09 13:02:13 +09:00
Hide_D 39c88c11c4 misc: 에러 확인을 위해 추가 메시지 2022-07-09 12:26:50 +09:00
Hide_D c2e956a639 misc: DTO 에러에서 name을 포함하여 알림 2022-07-09 12:13:15 +09:00
Hide_D 368f31d1fa fix: 유니크 옥션 인자 빠짐 수정 2022-07-09 12:12:15 +09:00
Hide_D d3390dc490 fix: 상인 등록 경매에서 warning 수정 2022-07-09 12:00:00 +09:00
Hide_D eb36b6a52f fix: vue script ts error 2022-07-08 21:47:13 +09:00
Hide_D be882000ad fix: 183년 이전 선포된 경우 공백지 출병을 시도하는 버그 수정 2022-07-08 15:53:37 +09:00
Hide_D 266c1c6a5b fix: 깃수 종료 시 열린 경매 자동 닫기 2022-07-07 22:00:12 +09:00
Hide_D 7864fe1e0f misc: 토너먼트, 베팅장 버튼을 약간 더 크게 2022-07-06 23:09:37 +09:00
Hide_D fe08fe0e2e fix: 누락된 스탯 유니크 설명 수정 2022-07-06 22:57:15 +09:00
Hide_D 87775a9471 game: 회피 발동시 피해 감소량을 1/5에서 1/6으로 버프 2022-07-06 22:52:20 +09:00
Hide_D 8089457aa8 game: 도구 유니크 밸런스 수정 2022-07-06 22:50:54 +09:00
Hide_D e443f92ddb fix: 초반 내정 기간에 NPC가 다중 선포가 가능한 버그 수정 2022-07-06 22:45:18 +09:00
Hide_D cb65666600 misc: 메인페이지 하단 바 높이를 약간 높임 2022-07-06 22:40:16 +09:00
Hide_D 6ed174e5dc game: 모반시도 삭제 2022-07-05 23:13:25 +09:00
Hide_D dd7f0ef3bf fix: 거병 커맨드가 막힌 없는 경우 사전 거병도 불가 2022-07-05 23:12:49 +09:00
Hide_D ec8e43a2a9 fix: 서버 목록에서 목록이 긴 경우에도 아이콘이 하나만 2022-07-05 23:05:11 +09:00
Hide_D a83b6b55cd feat: 천통국 내기 오픈시 메시지로 알림 2022-07-05 23:02:54 +09:00
Hide_D d43f15e096 fix: 빙의장도 사전 거병이 가능해야함 2022-07-05 22:39:40 +09:00
Hide_D e09fdefa68 feat,game: 사전 거병 기능 추가
- 건국은 게임 개시 2턴째부터 가능
2022-07-05 22:23:23 +09:00
Hide_D 2b483749bc game: 유산 포인트로 도시와 턴 시간을 동시에 설정할 수 없도록 변경 2022-07-05 20:18:02 +09:00
Hide_D 048d71920c fix: 변수명 수정 2022-07-05 19:29:58 +09:00
Hide_D 47366086d5 feat: 군주/외교권자에게 부대명 변경 기능 부여 2022-07-05 00:46:45 +09:00
Hide_D f9a73be82b game,refac: 토너먼트 진행 시간을 턴 시간에 맞춤(최소 5초) 2022-07-04 23:59:04 +09:00
Hide_D e7918469e5 refac: Util::valueFit을 Util::clamp로 2022-07-04 23:25:44 +09:00
Hide_D 687559a1a3 refac: 장수 삭제를 api로 이동 2022-07-02 02:43:10 +09:00
Hide_D 398c11e607 misc: 금액 선택에서 '+만' 활성화 2022-06-25 13:09:57 +09:00
Hide_D 191544d28b game: 삼모시네마틱유니버스 시나리오 업데이트 2022-06-25 13:06:25 +09:00
Hide_D 647c2439e3 feat: 유산 목록에서 로그를 더 가져올 수 있음 2022-06-25 12:22:25 +09:00
Hide_D da2a6f347a game: 도시 정보의 장수 순서를 실제 서버 실행 시간으로 변경 2022-06-24 21:49:02 +09:00
640 changed files with 34190 additions and 18565 deletions
-15
View File
@@ -1,15 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3,
"modules": false
}
]
],
"plugins": [
"lodash"
]
}
+6
View File
@@ -10,8 +10,10 @@
*.log
logs/*.txt
api_log.db
d_log/*.txt
d_log/*.zip
d_log/*.db
sess_*
*/logs/*.txt
*/logs/*/*.txt
@@ -65,3 +67,7 @@ ingame/js/*
ingame/css/*
gateway/js/*
gateway/css/*
*.db-journal
d_log/cachegrind.*
+2 -15
View File
@@ -15,9 +15,8 @@ return [
// Note that the **only** effect of choosing `'5.6'` is to infer
// that functions removed in php 7.0 exist.
// (See `backward_compatibility_checks` for additional options)
"target_php_version" => '8.1',
"minimum_target_php_version" => '8.1',
'backward_compatibility_checks ' => true,
"target_php_version" => '8.2',
"minimum_target_php_version" => '8.2',
'minimum_severity' => \Phan\Issue::SEVERITY_NORMAL,
'file_list' => [
@@ -29,8 +28,6 @@ return [
'hwe/_admin1_submit.php',
'hwe/_admin2.php',
'hwe/_admin2_submit.php',
'hwe/_admin4.php',
'hwe/_admin4_submit.php',
'hwe/_admin5.php',
'hwe/_admin5_submit.php',
'hwe/_admin7.php',
@@ -45,7 +42,6 @@ return [
'hwe/api.php',
'hwe/a_traffic.php',
'hwe/battle_simulator.php',
'hwe/b_battleCenter.php',
'hwe/b_betting.php',
'hwe/v_chiefCenter.php',
'hwe/b_currentCity.php',
@@ -58,7 +54,6 @@ return [
'hwe/b_myPage.php',
'hwe/v_processing.php',
'hwe/b_tournament.php',
'hwe/b_troop.php',
'hwe/c_tournament.php',
'hwe/func_auction.php',
'hwe/func_command.php',
@@ -83,7 +78,6 @@ return [
'hwe/j_board_article_add.php',
'hwe/j_board_comment_add.php',
'hwe/j_board_get_articles.php',
'hwe/j_die_immediately.php',
'hwe/j_diplomacy_destroy_letter.php',
'hwe/j_diplomacy_get_letter.php',
'hwe/j_diplomacy_respond_letter.php',
@@ -101,12 +95,6 @@ return [
'hwe/j_load_scenarios.php',
'hwe/j_map.php',
'hwe/j_map_recent.php',
'hwe/j_msg_contact_list.php',
'hwe/j_msg_decide_opt.php',
'hwe/j_msg_delete.php',
'hwe/j_msg_get_old.php',
'hwe/j_msg_get_recent.php',
'hwe/j_msg_submit.php',
'hwe/j_myBossInfo.php',
'hwe/j_raise_event.php',
'hwe/j_select_npc.php',
@@ -115,7 +103,6 @@ return [
'hwe/j_set_my_setting.php',
'hwe/j_set_npc_control.php',
'hwe/j_simulate_battle.php',
'hwe/j_troop.php',
'hwe/j_update_picked_general.php',
'hwe/j_vacation.php',
'hwe/lib.php',
+1 -1
View File
@@ -29,5 +29,5 @@
"josa",
"sammo"
],
"editor.tabSize": 2
"editor.tabSize": 4
}
+1
View File
@@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="dark">
<title>닫혀 있습니다.</title>
<script>
setTimeout(function(){
+1 -1
View File
@@ -1,6 +1,6 @@
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
of this software and associated documentation files (the "Software"), to deal
+12 -12
View File
@@ -8,26 +8,26 @@
],
"config": {
"platform": {
"php": "8.1"
"php": "8.2"
}
},
"require": {
"brandonwamboldt/utilphp": "^1.1",
"sergeytsalkov/meekrodb": "^2.3",
"league/plates": "^3.3",
"league/plates": "^3.5",
"vlucas/valitron": "^1.4",
"php-extended/php-tail": "^2.1",
"pguardiario/phpuri": "^1.0",
"symfony/lock": "^6.0",
"php-extended/php-tail": "^5.0",
"symfony/lock": "^6.2",
"ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^2.1",
"phan/phan": "^5.3",
"nette/caching": "^3.0",
"illuminate/database": "^9.12",
"illuminate/events": "^9.12",
"spatie/data-transfer-object": "^3.7",
"php-ds/php-ds": "^1.4"
"phan/phan": "^5.4",
"nette/caching": "^3.2",
"illuminate/database": "^10.0",
"illuminate/events": "^10.0",
"php-ds/php-ds": "^1.4",
"hided62/ldto": "^1.0",
"league/uri": "^6.8"
},
"autoload": {
"psr-4": {
@@ -48,6 +48,6 @@
]
},
"require-dev": {
"phpunit/phpunit": "^9.5"
"phpunit/phpunit": "^10.0"
}
}
Generated
+1079 -875
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+4 -3
View File
@@ -10,6 +10,7 @@ require(__DIR__ . '/../vendor/autoload.php');
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>설치</title>
@@ -29,10 +30,10 @@ require(__DIR__ . '/../vendor/autoload.php');
<body>
<div class="container">
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 설치</h1>
<div class="row justify-content-md-center">
<h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 설치</h1>
<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">
<h3 class="card-header">
설치(DB 설정)
+4 -4
View File
@@ -90,19 +90,19 @@ if (
//기본 파일 생성
if (!file_exists(AppConf::getUserIconPathFS())) {
mkdir(AppConf::getUserIconPathFS());
mkdir(AppConf::getUserIconPathFS(), 0775);
}
if (!file_exists(ROOT . '/d_log')) {
mkdir(ROOT . '/d_log');
mkdir(ROOT . '/d_log', 0775);
}
if (!file_exists(ROOT . '/d_setting')) {
mkdir(ROOT . '/d_setting');
mkdir(ROOT . '/d_setting', 0775);
}
if (!file_exists(ROOT . '/d_shared')) {
mkdir(ROOT . '/d_shared');
mkdir(ROOT . '/d_shared', 0775);
}
}
+17
View File
@@ -0,0 +1,17 @@
CREATE TABLE IF NOT EXISTS "api_log" (
"id" INTEGER NOT NULL,
"user_id" INTEGER NOT NULL,
"ip" TEXT NOT NULL,
"date" TEXT NOT NULL,
"path" TEXT NOT NULL,
"arg" TEXT,
"aux" TEXT,
PRIMARY KEY("id" AUTOINCREMENT)
);
CREATE INDEX IF NOT EXISTS "by_date" ON "api_log" (
"date" DESC
);
CREATE INDEX IF NOT EXISTS "by_user" ON "api_log" (
"user_id" ASC,
"date" DESC
);
-5
View File
@@ -61,11 +61,6 @@ class RootDB
if (self::$uDB === null) {
self::$uDB = new \MeekroDB(self::$host, self::$user, self::$password, self::$dbName, self::$port, self::$encoding);
self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
self::$uDB->error_handler = function () {
};
self::$uDB->throw_exception_on_error = true;
self::$uDB->throw_exception_on_nonsql_error = true;
}
return self::$uDB;
}
+58
View File
@@ -165,3 +165,61 @@
background: url('_tK_gameImagePath_/map/pokemon_v1/back_pal8.png') no-repeat;
background-size: 700px 500px;
}
/*CR 지도*/
.map_theme_cr .map_bglayer1{
background: url('_tK_gameImagePath_/map/cr/bg-fs8.png') no-repeat;
background-size: 700px 500px;
}
.map_theme_cr.map_detail .city_base .city_bg {
background-image: none !important;
width: 39.5px !important;
height: 39.5px !important;
left: 1px !important;
top: -4px !important;
opacity: 0.5;
}
.map_theme_cr.map_detail.small_width_map .city_base .city_bg {
background-image: none !important;
width: 28.5px !important;
height: 28.5px !important;
left: 6px !important;
top: 4px !important;
opacity: 0.5;
}
.map_theme_cr.map_detail .city_bg.bFF0000 { background-color: #FF0000; }
.map_theme_cr.map_detail .city_bg.b800000 { background-color: #800000; }
.map_theme_cr.map_detail .city_bg.bA0522D { background-color: #A0522D; }
.map_theme_cr.map_detail .city_bg.bFF6347 { background-color: #FF6347; }
.map_theme_cr.map_detail .city_bg.bFFA500 { background-color: #FFA500; }
.map_theme_cr.map_detail .city_bg.bFFDAB9 { background-color: #FFDAB9; }
.map_theme_cr.map_detail .city_bg.bFFD700 { background-color: #FFD700; }
.map_theme_cr.map_detail .city_bg.bFFFF00 { background-color: #FFFF00; }
.map_theme_cr.map_detail .city_bg.b7CFC00 { background-color: #7CFC00; }
.map_theme_cr.map_detail .city_bg.b00FF00 { background-color: #00FF00; }
.map_theme_cr.map_detail .city_bg.b808000 { background-color: #808000; }
.map_theme_cr.map_detail .city_bg.b008000 { background-color: #008000; }
.map_theme_cr.map_detail .city_bg.b2E8B57 { background-color: #2E8B57; }
.map_theme_cr.map_detail .city_bg.b008080 { background-color: #008080; }
.map_theme_cr.map_detail .city_bg.b20B2AA { background-color: #20B2AA; }
.map_theme_cr.map_detail .city_bg.b6495ED { background-color: #6495ED; }
.map_theme_cr.map_detail .city_bg.b7FFFD4 { background-color: #7FFFD4; }
.map_theme_cr.map_detail .city_bg.bAFEEEE { background-color: #AFEEEE; }
.map_theme_cr.map_detail .city_bg.b87CEEB { background-color: #87CEEB; }
.map_theme_cr.map_detail .city_bg.b00FFFF { background-color: #00FFFF; }
.map_theme_cr.map_detail .city_bg.b00BFFF { background-color: #00BFFF; }
.map_theme_cr.map_detail .city_bg.b0000FF { background-color: #0000FF; }
.map_theme_cr.map_detail .city_bg.b000080 { background-color: #000080; }
.map_theme_cr.map_detail .city_bg.b483D8B { background-color: #483D8B; }
.map_theme_cr.map_detail .city_bg.b7B68EE { background-color: #7B68EE; }
.map_theme_cr.map_detail .city_bg.bBA55D3 { background-color: #BA55D3; }
.map_theme_cr.map_detail .city_bg.b800080 { background-color: #800080; }
.map_theme_cr.map_detail .city_bg.bFF00FF { background-color: #FF00FF; }
.map_theme_cr.map_detail .city_bg.bFFC0CB { background-color: #FFC0CB; }
.map_theme_cr.map_detail .city_bg.bF5F5DC { background-color: #F5F5DC; }
.map_theme_cr.map_detail .city_bg.bE0FFFF { background-color: #E0FFFF; }
.map_theme_cr.map_detail .city_bg.bFFFFFF { background-color: #FFFFFF; }
.map_theme_cr.map_detail .city_bg.bA9A9A9 { background-color: #A9A9A9; }
+1
View File
@@ -21,6 +21,7 @@ $plock = $db->queryFirstField('SELECT plock FROM plock WHERE `type` ="GAME"');
<head>
<title>삼국지 모의전투 HiDCHe</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')?>
+1 -2
View File
@@ -19,6 +19,7 @@ $admin = getAdmin();
<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')?>
@@ -40,8 +41,6 @@ $admin = getAdmin();
<tr>
<td width=110 align=right>시작시간변경</td>
<td width=285><input type=text size=20 maxlength=20 style=color:white;background-color:black;text-align:right; name=starttime value='<?=substr($admin['starttime'], 0, 19)?>'><input type=submit name=btn value=변경1></td>
<td width=110 align=right>현재도시훈사</td>
<td width=285><?=$admin['city_rate']?></td>
</tr>
<tr>
<td width=110 align=right>최대 장수</td>
+1 -22
View File
@@ -74,28 +74,7 @@ switch ($btn) {
case "120분턴": $turnterm = 120; break;
default: throw new \Exception("알 수 없는 턴 기간");
}
$oldunit = $admin['turnterm'] * 60;
$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</>으로 변경됩니다."]);
ServerTool::changeServerTerm($turnterm);
break;
}
+1
View File
@@ -20,6 +20,7 @@ $db = DB::db();
<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') ?>
+21 -19
View File
@@ -2,6 +2,8 @@
namespace sammo;
use sammo\Enums\MessageType;
include "lib.php";
include "func.php";
@@ -31,18 +33,18 @@ $src = MessageTarget::buildQuick($session->generalID);
$genObjList = [];
$env = [];
if ($genlist) {
$genObjList = General::createGeneralObjListFromDB($genlist);
$genObjList = General::createObjListFromDB($genlist);
$env = $gameStor->cacheAll();
}
switch ($btn) {
case "전체 접속허용":
$db->update('general', [
'con' => 0
$db->update('general_access_log', [
'refresh_score' => 0
], true);
break;
case "전체 접속제한":
$db->update('general', [
'con' => 1000
$db->update('general_access_log', [
'refresh_score' => 1000
], true);
break;
case "블럭 해제":
@@ -111,7 +113,7 @@ switch ($btn) {
case "경험치1000":
$text = $btn . " 지급!";
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
@@ -122,7 +124,7 @@ switch ($btn) {
case "공헌치1000":
$text = $btn . " 지급!";
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
@@ -133,7 +135,7 @@ switch ($btn) {
case "보숙10000":
$text = "보병숙련도+10000 지급!";
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
@@ -143,7 +145,7 @@ switch ($btn) {
case "궁숙10000":
$text = "궁병숙련도+10000 지급!";
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
@@ -154,7 +156,7 @@ switch ($btn) {
$src = MessageTarget::buildQuick($session->generalID);
$text = "기병숙련도+10000 지급!";
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
@@ -165,7 +167,7 @@ switch ($btn) {
$src = MessageTarget::buildQuick($session->generalID);
$text = "귀병숙련도+10000 지급!";
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
@@ -176,7 +178,7 @@ switch ($btn) {
$src = MessageTarget::buildQuick($session->generalID);
$text = "차병숙련도+10000 지급!";
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
@@ -184,19 +186,19 @@ switch ($btn) {
], '`no` IN %li', $genlist);
break;
case "접속 허용":
$db->update('general', [
'con' => 0
], '`no` IN %li', $genlist);
$db->update('general_access_log', [
'refresh_score' => 0
], '`general_id` IN %li', $genlist);
break;
case "접속 제한":
$db->update('general', [
'con' => 1000
], '`no` IN %li', $genlist);
$db->update('general_access_log', [
'refresh_score' => 1000
], '`general_id` IN %li', $genlist);
break;
case "메세지 전달":
$text = $msg ?? '';
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg = new Message(MessageType::private, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
break;
-132
View File
@@ -1,132 +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 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>
-84
View File
@@ -1,84 +0,0 @@
<?php
namespace sammo;
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(
Message::MSGTYPE_PRIVATE,
$src,
MessageTarget::buildQuick($generalID),
$msg,
new \DateTime(),
new \DateTime('9999-12-31'),
[]
);
if ($msgObj) {
$msgObj->send(true);
}
}
break;
}
header('location:_admin4.php');
+1 -14
View File
@@ -38,6 +38,7 @@ $sel2[$type2] = "selected";
<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') ?>
@@ -65,8 +66,6 @@ $sel2[$type2] = "selected";
<option <?= $sel[8] ?? '' ?> value=8>평무</option>
<option <?= $sel[9] ?? '' ?> value=9>평지</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[14] ?? '' ?> value=14>궁숙</option>
<option <?= $sel[15] ?? '' ?> value=15>기숙</option>
@@ -104,8 +103,6 @@ $sel2[$type2] = "selected";
<table align=center width=1600 class="tb_layout bg0">
<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>
@@ -146,8 +143,6 @@ SELECT
A.gold,
A.rice,
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.dex2)) AS dex2,
ROUND(AVG(B.dex3)) AS dex3,
@@ -192,12 +187,6 @@ GROUP BY B.nation
case 10:
$query .= " order by avg(B.explevel) desc";
break;
case 11:
$query .= " order by avg(B.connect) desc";
break;
case 12:
$query .= " order by avg(B.con) desc";
break;
case 13:
$query .= " order by avg(B.dex1) desc";
break;
@@ -239,8 +228,6 @@ from city where nation=%i', $nation['nation']);
echo "
<tr>
<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;{$gen['cnt']}&nbsp;</td>
<td align=center>&nbsp;{$city['cnt']}&nbsp;</td>
+4 -1
View File
@@ -2,6 +2,8 @@
namespace sammo;
use sammo\Enums\GeneralQueryMode;
include "lib.php";
include "func.php";
@@ -74,7 +76,7 @@ if (!$gen) {
$gen = $generalBasicList[0]['no'];
}
$generalObj = General::createGeneralObjFromDB($gen);
$generalObj = General::createObjFromDB($gen, null, GeneralQueryMode::FullWithAccessLog);
?>
<!DOCTYPE html>
@@ -83,6 +85,7 @@ $generalObj = General::createGeneralObjFromDB($gen);
<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') ?>
+1
View File
@@ -30,6 +30,7 @@ $sel[$type] = "selected";
<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') ?>
+2 -3
View File
@@ -26,8 +26,7 @@ foreach ($db->queryFirstColumn(
}
$inheritPointManager = InheritancePointManager::getInstance();
foreach(General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){
$inheritPointManager->mergeTotalInheritancePoint($genObj, true);
foreach(General::createObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){
$inheritPointManager->mergeTotalInheritancePoint($genObj);
$inheritPointManager->applyInheritanceUser($genObj->getVar('owner'));
$inheritPointManager->clearInheritancePoint($genObj);
}
+2
View File
@@ -28,12 +28,14 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates');
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 명장일람</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common', 'bestGeneral']) ?>
</head>
+2
View File
@@ -14,12 +14,14 @@ increaseRefresh("왕조일람", 1);
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 왕조일람</title>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', 'common') ?>
</head>
+2
View File
@@ -24,10 +24,12 @@ $serverID = $emperior['server_id'] ?? ($emperior['serverID'] ?? null);
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 왕조일람</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', 'common', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
+18 -8
View File
@@ -16,10 +16,13 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
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']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
printLimitMsg($me['turntime']);
exit();
}
@@ -41,12 +44,14 @@ if ($gameStor->isunited) {
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 장수일람</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', 'common') ?>
</head>
@@ -100,7 +105,7 @@ if ($gameStor->isunited) {
6 => ['dedication', true],
7 => ['officer_level', true],
8 => ['killturn', false],
9 => ['connect', true],
9 => ['refresh_score_total', true],
10 => ['experience', true],
11 => ['personal', true],
12 => ['special', true],
@@ -109,7 +114,12 @@ if ($gameStor->isunited) {
15 => ['npc', true],
][$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 "
<table align=center width=1000 class='tb_layout bg0'>
@@ -161,7 +171,7 @@ if ($gameStor->isunited) {
$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']);
echo "
@@ -190,8 +200,8 @@ if ($gameStor->isunited) {
<td align=center>$strength</td>
<td align=center>$intel</td>
<td align=center>{$general['killturn']}</td>
<td align=center>{$general['connect']}";
echo "<br>【" . getConnect($general['connect']) . "】</td>
<td align=center>" . $general['refresh_score_total'] ?? 0;
echo "<br>【" . getRefreshScoreText($general['refresh_score_total'] ?? 0) . "】</td>
</tr>";
}
echo "
+2
View File
@@ -43,12 +43,14 @@ if ($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx] ?? [])) {
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 명예의 전당</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common', 'hallOfFame']) ?>
</head>
+8 -3
View File
@@ -13,10 +13,13 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['killturn', 'autorun_user', 'turnterm']);
increaseRefresh("세력일람", 2);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
$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']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
printLimitMsg($me['turntime']);
exit();
}
@@ -26,12 +29,14 @@ if ($con >= 2) {
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 세력일람</title>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common', 'extKingdoms']) ?>
<?= WebUtil::printStaticValues($gameStor->getValues(['killturn', 'autorun_user', 'turnterm'])) ?>
</head>
+2
View File
@@ -24,12 +24,14 @@ $sel[$type] = "selected";
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 빙의일람</title>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common']) ?>
</head>
+34 -34
View File
@@ -2,36 +2,29 @@
namespace sammo;
use sammo\Enums\GeneralAccessLogColumn;
include "lib.php";
include "func.php";
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("갱신정보", 2);
increaseRefresh("갱신정보", 1);
$admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxrefresh', 'maxonline']);
$admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxrefresh', 'maxonline', 'recentTraffic']);
$log = getRawFileLogRecent(__DIR__ . '/logs/' . UniqueConst::$serverID . '/_traffic.txt', 11, 100);
$date = [];
$year = [];
$month = [];
$refresh = [];
$online = [];
$recentTraffic = $admin['recentTraffic'] ?? [];
$curonline = getOnlineNum();
foreach ($log as $i => $value) {
$parse = Json::decode($value);
$date[$i] = $parse[0];
$year[$i] = $parse[1];
$month[$i] = $parse[2];
$refresh[$i] = $parse[3];
$online[$i] = $parse[4];
}
$year[] = $admin['year'];
$month[] = $admin['month'];
$date[] = TimeUtil::now();
$recentTraffic[] = [
'year' => $admin['year'],
'month' => $admin['month'],
'refresh' => $admin['refresh'],
'online' => $curonline,
'date' => TimeUtil::now()
];
if ($admin['maxrefresh'] == 0) {
$admin['maxrefresh'] = 1;
@@ -52,6 +45,7 @@ if ($admin['maxonline'] < $curonline) {
<head>
<title><?= UniqueConst::$serverName ?>: 트래픽정보</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') ?>
@@ -83,6 +77,7 @@ if ($admin['maxonline'] < $curonline) {
}
</style>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common']) ?>
</head>
@@ -103,13 +98,13 @@ if ($admin['maxonline'] < $curonline) {
</td>
</tr>
<?php
$refresh[] = $admin['refresh'];
foreach ($refresh as $i => $value) {
foreach ($recentTraffic as $trafficItem) {
$value = $trafficItem['refresh'];
$w = round($value / $admin['maxrefresh'] * 100, 1);
$color = getTrafficColor($w);
$dt = substr($date[$i], 11, 5); ?>
$dt = substr($trafficItem['date'], 11, 5); ?>
<tr height=30>
<td width=100 align=center><?= $year[$i] ?>년 <?= $month[$i] ?>월</td>
<td width=100 align=center><?= $trafficItem['year'] ?>년 <?= $trafficItem['month'] ?>월</td>
<td width=60 align=center class='bg2'><?= $dt ?></td>
<td width=2 align=center class='bg1'></td>
<td width=320>
@@ -144,13 +139,13 @@ if ($admin['maxonline'] < $curonline) {
</td>
</tr>
<?php
$online[] = $curonline;
foreach ($online as $i => $value) {
foreach ($recentTraffic as $trafficItem) {
$value = $trafficItem['online'];
$w = round($value / $admin['maxonline'] * 100, 1);
$color = getTrafficColor($w);
$dt = substr($date[$i], 11, 5); ?>
$dt = substr($trafficItem['date'], 11, 5); ?>
<tr height=30>
<td width=100 align=center><?= $year[$i] ?>년 <?= $month[$i] ?>월</td>
<td width=100 align=center><?= $trafficItem['year'] ?>년 <?= $trafficItem['month'] ?>월</td>
<td width=60 align=center class='bg2'><?= $dt ?></td>
<td width=2 align=center class='bg1'></td>
<td width=320>
@@ -185,19 +180,24 @@ if ($admin['maxonline'] < $curonline) {
</td>
</tr>
<?php
$max_refresh = $db->queryFirstRow('SELECT sum(refresh) as refresh, sum(`connect`) as `connect` from general');
$max_refresh['name'] = '접속자 총합';
$totalRefresh = [
...$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) {
$w = round($user['refresh'] / max(1, $max_refresh['refresh']) * 100, 1);
foreach (array_merge([$totalRefresh], $top5Refresh) as $i => $user) {
$w = round($user['refresh'] / max(1, $totalRefresh['refresh']) * 100, 1);
$w2 = round(100 - $w, 1);
$color = getTrafficColor($w);
?>
<tr>
<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>
<?php if ($w == 0) : ?>
<?php elseif ($w < 10) : ?>
-208
View File
@@ -1,208 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$v = new Validator($_POST + $_GET);
$v->rule('required', 'gen')
->rule('integer', 'gen');
$btn = Util::getReq('btn');
$gen = Util::getReq('gen', 'int', 0);
$reqQueryType = Util::getReq('query_type', 'string', null);
// $queryTypeText, $reqArgType(0=>None, 1=>AdditionalColumn, 2=>rankVal, 3=>aux), $comp
$queryMap = [
'turntime' => ['최근턴', 0, function ($lhs, $rhs) {
return - ($lhs['turntime'] <=> $rhs['turntime']);
}],
'recent_war' => ['최근전투', 1, function ($lhs, $rhs) {
return - ($lhs['recent_war'] <=> $rhs['recent_war']);
}],
'name' => ['장수명', 0, function ($lhs, $rhs) {
if ($lhs['npc'] !== $rhs['npc']) {
return $lhs['npc'] <=> $rhs['npc'];
}
return $lhs['name'] <=> $rhs['name'];
}],
'warnum' => ['전투수', 2, function ($lhs, $rhs) {
return - ($lhs['warnum'] <=> $rhs['warnum']);
}]
];
if ($reqQueryType === null || !key_exists($reqQueryType, $queryMap)) {
$reqQueryType = Util::array_first_key($queryMap);
}
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("감찰부", 2);
//전투 추진을 위해 갱신
TurnExecutionHelper::executeAllCommand();
$gameStor->resetCache();
$testGeneralNationID = $db->queryFirstField('SELECT nation FROM general WHERE no = %i', $gen);
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,permission,penalty from general where owner=%i', $userID);
$nationID = $me['nation'];
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
$permission = checkSecretPermission($me);
if ($permission < 0) {
echo '국가에 소속되어있지 않습니다.';
die();
} else if ($permission < 1) {
echo "권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.";
die();
}
//잘못된 접근
if ($testGeneralNationID != $nationID) {
$gen = 0;
}
if ($btn == '정렬') {
$gen = 0;
}
[$queryTypeText, $reqArgType, $comp] = $queryMap[$reqQueryType];
if ($reqArgType === 0) {
$generalBasicList = $db->query('SELECT no, name, npc, turntime, officer_level FROM general WHERE nation = %i', $nationID);
} else if ($reqArgType === 1) {
$generalBasicList = $db->query('SELECT no, name, npc, turntime, officer_level, %b FROM general WHERE nation = %i', $reqQueryType, $nationID);
} else if ($reqArgType === 2) {
$generalBasicList = $db->query(
'SELECT no, name, npc, turntime, officer_level, value as %b
FROM general LEFT JOIN rank_data
ON general.no = rank_data.general_id
WHERE rank_data.type = %s AND general.nation = %i',
$reqQueryType,
$reqQueryType,
$nationID
);
} else if ($reqArgType === 3) {
$generalBasicList = array_map(function ($arr) {
$arr['aux'] = Json::decode($arr['aux']);
return $arr;
}, $db->query('SELECT no, name, npc, turntime, officer_level, aux FROM general WHERE nation = %i', $nationID));
} else {
throw new \sammo\MustNotBeReachedException();
}
usort($generalBasicList, $comp);
if (!$gen) {
$gen = $generalBasicList[0]['no'];
}
$showGeneral = General::createGeneralObjFromDB($gen);
?>
<!DOCTYPE html>
<html>
<head>
<title><?= UniqueConst::$serverName ?>: 감찰부</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('ts', ['common', 'battleCenter']) ?>
</head>
<body>
<div id="container" class="bg0">
<div class="row gx-0">
<div class="col">감 찰 부<br><?= closeButton() ?></div>
</div>
<div class="row gx-0">
<div class="col-12" style="border-left: solid 1px gray; border-right:solid 1px gray;">
<form name=form1 method=get>
정렬순서 :
<select name='query_type' size=1>
<?php foreach ($queryMap as $queryType => [$queryTypeText,]) : ?>
<option <?= $queryType == $reqQueryType ? 'selected' : '' ?> value='<?= $queryType ?>'><?= $queryTypeText ?></option>
<?php endforeach; ?>
</select>
<input type=submit name=btn value='정렬'>
대상장수 :
<select name=gen size=1>
<?php foreach ($generalBasicList as $general) : ?>
<option <?= $gen == $general['no'] ? 'selected' : '' ?> value='<?= $general['no'] ?>'><?= $general['officer_level'] > 4 ? "*{$general['name']}*" : $general['name'] ?> (<?= substr($general['turntime'], 14, 5) ?>)</option>
<?php endforeach; ?>
</select>
<input type=submit name=btn value='조회'>
</form>
</div>
<div class="col col-12 col-md-6">
<div class="row mx-0">
<div class="col bg1 header-cell" style="color:skyblue">장수 정보</div>
</div>
<div class="row">
<div class="col"><?php generalInfo($showGeneral); ?><?php generalInfo2($showGeneral); ?></div>
</div>
</div>
<div class="col col-12 col-md-6">
<div class="row mx-0">
<div class="col bg1 header-cell">장수 열전</div>
</div>
<div class="row">
<div class="col"><?= formatHistoryToHTML(getGeneralHistoryLogAll($gen)) ?></div>
</div>
</div>
<div class="col col-12 col-md-6">
<div class="row mx-0">
<div class="col bg1 header-cell">전투 기록</div>
</div>
<div class="row">
<div class="col"><?= formatHistoryToHTML(getBattleDetailLogRecent($gen, 24)) ?></div>
</div>
</div>
<div class="col col-12 col-md-6">
<div class="row mx-0">
<div class="col bg1 header-cell">전투 결과</div>
</div>
<div class="row">
<div class="col"><?= formatHistoryToHTML(getBattleResultRecent($gen, 24)) ?></div>
</div>
</div>
<?php if ($showGeneral->getNPCType() > 1 || $permission >= 2) : ?>
<div class="col col-12 col-md-6">
<div class="row mx-0">
<div class="col bg1 header-cell">개인 기록</div>
</div>
<div class="row">
<div class="col"><?= formatHistoryToHTML(getGeneralActionLogRecent($gen, 24)) ?></div>
</div>
</div>
<?php endif; ?>
</div>
<div class="row gx-0">
<div class="col "><?= closeButton() ?></div>
</div>
<div class="row bg0 gx-0">
<div class="col bg0"><?= banner() ?></div>
</div>
</div>
</body>
</html>
+26 -19
View File
@@ -2,6 +2,8 @@
namespace sammo;
use sammo\Enums\GeneralLiteQueryMode;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\RankColumn;
include "lib.php";
@@ -21,12 +23,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', 'develcost']);
$con = checkLimit($me['con']);
if ($con >= 2) {
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'turnterm', 'develcost']);
$turnTerm = $admin['turnterm'];
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
printLimitMsg($me['turntime']);
exit();
}
@@ -99,7 +104,7 @@ $str2 = getTournamentTime();
if ($str2) {
$str2 = ', ' . $str2;
}
$str3 = getTournamentTermText();
$str3 = getTournamentTermText($turnTerm);
if ($str3) {
$str3 = ', ' . $str3;
}
@@ -107,18 +112,20 @@ if ($str3) {
?>
<!DOCTYPE html>
<html>
<?php if ($con == 1) {
<?php if ($limitState == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!");
} ?>
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 베팅장</title>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common', 'betting']) ?>
<?= WebUtil::printStaticValues([
'staticValues'=>[
@@ -135,7 +142,7 @@ if ($str3) {
</table>
<table align=center width=1120 class='tb_layout bg0'>
<tr>
<td colspan=16><input type=button value='갱신' onclick='location.reload()'></td>
<td colspan=16><button type="button" class="btn btn-secondary" onclick='location.reload()'>갱신</button></td>
</tr>
<tr>
<td colspan=16 align=center>
@@ -441,13 +448,13 @@ if ($str3) {
if ($admin['tournament'] == 6) {
echo "
<tr align=center>";
<tr align=center style='height:2.5em;'>";
foreach (range(0, 15) as $i) {
$key = $keyMap[$i] ?? -1;
echo "
<td>
<select size=1 id='target_{$key}' style=color:white;background-color:black;>
<select size=1 id='target_{$key}' style='color:white;background-color:black;padding:0.2rem 0.1rem;'>
<option style=color:white; value=10>금10</option>
<option style=color:white; value=20>금20</option>
<option style=color:white; value=50>금50</option>
@@ -461,12 +468,12 @@ if ($str3) {
echo "
</tr>
<tr align=center>";
<tr align=center style='height:2.2em;'>";
foreach (range(0, 15) as $i) {
$key = $keyMap[$i] ?? -1;
echo "
<td><input type=button class='submitBtn' data-target='{$key}' value=베팅! style=width:100%;color:white;background-color:black;></td>";
<td><input type=button class='submitBtn' data-target='{$key}' value=베팅! style='width:100%;color:white;padding:0.2rem 0.1rem;background-color:black;'></td>";
}
echo "</tr>";
@@ -500,28 +507,28 @@ if ($str3) {
$tournamentType = [
'전 력 전' => [
'종합',
function (General $general) {
function (GeneralLite $general) {
return $general->getVar('leadership') + $general->getVar('strength') + $general->getVar('intel');
},
'tt',
],
'통 솔 전' => [
'통솔',
function (General $general) {
function (GeneralLite $general) {
return $general->getVar('leadership');
},
'tl',
],
'일 기 토' => [
'무력',
function (General $general) {
function (GeneralLite $general) {
return $general->getVar('strength');
},
'ts',
],
'설 전' => [
'지력',
function (General $general) {
function (GeneralLite $general) {
return $general->getVar('intel');
},
'ti',
@@ -558,12 +565,12 @@ if ($str3) {
$winColumn = RankColumn::from("{$rankColumn}w");
$drawColumn = RankColumn::from("{$rankColumn}d");
$loseColumn = RankColumn::from("{$rankColumn}l");
$tournamentRankerList = General::createGeneralObjListFromDB(
$tournamentRankerList = GeneralLite::createObjListFromDB(
$db->queryFirstColumn('SELECT general_id FROM rank_data WHERE `type`= %s ORDER BY value DESC LIMIT 40', $gameColumn->value),
[$prizeColumn->value, $gameColumn->value, $winColumn->value, $drawColumn->value, $loseColumn->value, 'leadership', 'strength', 'intel', 'no', 'npc', 'name'],
0
GeneralLiteQueryMode::Core
);
usort($tournamentRankerList, function (General $lhs, General $rhs) use ($gameColumn, $winColumn, $drawColumn, $loseColumn) {
usort($tournamentRankerList, function (GeneralLite $lhs, GeneralLite $rhs) use ($gameColumn, $winColumn, $drawColumn, $loseColumn) {
$result = - ($lhs->getRankVar($gameColumn) <=> $rhs->getRankVar($gameColumn));
if ($result !== 0) return $result;
$result = - (
+8 -5
View File
@@ -13,9 +13,11 @@ $userID = Session::getUserID();
$userGrade = Session::getUserGrade();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("현재도시", 1);
$lastExecute = substr($gameStor->turntime, 5, 14);
$me = $db->queryFirstRow('SELECT no,nation,officer_level,city from general where owner=%i', $userID);
$myNation = $db->queryFirstRow('SELECT nation,level,spy FROM nation WHERE nation=%i', $me['nation']) ?? [
'nation' => 0,
@@ -32,6 +34,7 @@ $templates = new \League\Plates\Engine('templates');
<head>
<title><?= UniqueConst::$serverName ?>: 도시정보</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::printJS('../d_shared/common_path.js') ?>
@@ -53,6 +56,7 @@ $templates = new \League\Plates\Engine('templates');
font-size: x-small;
}
</style>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common', 'currentCity']) ?>
</head>
@@ -207,7 +211,7 @@ $templates = new \League\Plates\Engine('templates');
$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) {
$generals = $db->query(
'SELECT %l from general where city=%i order by turntime',
@@ -323,8 +327,7 @@ $templates = new \League\Plates\Engine('templates');
if ($ourGeneral && !$isNPC) {
$turnText = [];
$generalObj = new General($general, null, null, null, null, null, false);
foreach ($generalTurnList[$generalObj->getID()] as $turnRawIdx => $turn) {
foreach ($generalTurnList[$general['no']] as $turnRawIdx => $turn) {
$turnIdx = $turnRawIdx + 1;
$turnText[] = "{$turnIdx} : $turn";
}
@@ -446,7 +449,7 @@ $templates = new \League\Plates\Engine('templates');
<table align=center width=1000 class='tb_layout bg2'>
<tr>
<td colspan=11 align=center style='color:<?= newColor($cityNation['color']) ?>; background:<?= $cityNation['color'] ?>'>【 <?= CityConst::$regionMap[$city['region']] ?> | <?= CityConst::$levelMap[$city['level']] ?> 】 <?= $city['name'] ?></td>
<td style='color:<?= newColor($cityNation['color']) ?>; background:<?= $cityNation['color'] ?>' class='center'><?= date('m-d H:i:s') ?></td>
<td style='color:<?= newColor($cityNation['color']) ?>; background:<?= $cityNation['color'] ?>' class='center'><?= $lastExecute ?></td>
</tr>
<tr>
<td align=center width=48 class=bg1>주민</td>
+9 -4
View File
@@ -19,12 +19,15 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("암행부", 1);
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,permission,penalty from general where owner=%i', $userID);
$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']);
$con = checkLimit($me['con']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
printLimitMsg($me['turntime']);
exit();
}
@@ -45,18 +48,20 @@ $templates = new \League\Plates\Engine('templates');
?>
<!DOCTYPE html>
<html>
<?php if ($con == 1) {
<?php if ($limitState == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!");
} ?>
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 암행부</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common']) ?>
</head>
+2
View File
@@ -42,6 +42,7 @@ if ($meLevel >= 5) {
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 인사부</title>
@@ -54,6 +55,7 @@ if ($meLevel >= 5) {
var chiefStatMin = <?= GameConst::$chiefStatMin ?>;
var myLevel = <?= $meLevel ?>;
</script>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common', 'bossInfo']) ?>
<?php
+2
View File
@@ -33,12 +33,14 @@ $sel = [$type => "selected"];
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 세력도시</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common', 'extExpandCity']) ?>
</head>
+8 -4
View File
@@ -42,12 +42,14 @@ if ($gameStor->isunited) {
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 세력장수</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common']) ?>
</head>
@@ -95,7 +97,7 @@ if ($gameStor->isunited) {
7 => ['gold', true],
8 => ['rice', true],
9 => ['crew', true],
10 => ['connect', true],
10 => ['refresh_score_total', true],
11 => ['personal', true],
12 => ['special', true],
13 => ['special2', true],
@@ -103,7 +105,9 @@ if ($gameStor->isunited) {
15 => ['npc', true],
][$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 "
<table align=center class='tb_layout bg0'>
@@ -171,8 +175,8 @@ if ($gameStor->isunited) {
<td align=center>" . displayCharInfo($general['personal']) . "</td>
<td align=center>" . displaySpecialDomesticInfo($general['special']) . " / " . displaySpecialWarInfo($general['special2']) . "</td>
<td align=center>{$general['belong']}</td>
<td align=center>{$general['connect']}";
echo "<br>(" . getConnect($general['connect']) . ")</td>
<td align=center>". $general['refresh_score_total'] ?? 0;
echo "<br>(" . getRefreshScoreText($general['refresh_score_total'] ?? 0) . ")</td>
</tr>";
}
echo "
+2
View File
@@ -25,12 +25,14 @@ if ($nationID == 0) {
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 세력정보</title>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common']) ?>
</head>
+56 -18
View File
@@ -2,11 +2,16 @@
namespace sammo;
use sammo\Enums\GeneralAccessLogColumn;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\TableName;
include "lib.php";
include "func.php";
$showDieImmediatelyBtn = false;
$availableDieImmediately = false;
$showDieOnPrestartBtn = false;
$showBuildNationCandidateBtn = false;
$availableDieOnPrestart = false;
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
@@ -19,7 +24,7 @@ $gameStor->cacheValues(['turntime', 'opentime', 'autorun_user', 'npcmode']);
increaseRefresh("내정보", 1);
$me = General::createGeneralObjFromDB($generalID);
$me = General::createObjFromDB($generalID, null, GeneralQueryMode::FullWithAccessLog);
$myset = $me->getVar('myset');
if ($myset > 0) {
@@ -28,30 +33,49 @@ if ($myset > 0) {
$submit = 'hidden';
}
$targetTime = addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, 2);
$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 ($me->getNPCType() == 0) {
$showDieImmediatelyBtn = true;
if ($me->getNPCType() == 0 && $me->getNationID() == 0) {
$showDieOnPrestartBtn = true;
if ($targetTime <= TimeUtil::now()) {
$availableDieImmediately = true;
$availableDieOnPrestart = true;
}
}
if ($me->getNationID() == 0) {
$showBuildNationCandidateBtn = true;
}
}
$use_treatment = $me->getAuxVar('use_treatment') ?? 10;
$use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
$changeDefence999Train = -3;
$changeDefence999Atmos = -6;
$changeDefence999Train = $me->onCalcDomestic('changeDefenceTrain', "train999", $changeDefence999Train);
$changeDefence999Atmos = $me->onCalcDomestic('changeDefenceTrain', "atmos999", $changeDefence999Atmos);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 내정보</title>
<?= WebUtil::printStaticValues([
'availableDieImmediately' => $availableDieImmediately,
'availableDieOnPrestart' => $availableDieOnPrestart,
'staticValues' => [
'items' => Util::mapWithKey(fn (string $key, BaseItem $item) => [
'name' => $item->getName(),
@@ -65,6 +89,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['myPage']) ?>
</head>
@@ -74,13 +99,13 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<div class="col">내 정 보<br><?= backButton() ?></div>
</div>
<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="col"><?php generalInfo($me); ?><?php generalInfo2($me); ?></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="col" style='padding-left:2ch;'>
토너먼트 【
@@ -110,7 +135,10 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<?php foreach ([90, 80, 60, 40] as $targetDefenceTrain) : ?>
<option value='<?= $targetDefenceTrain ?>' <?= $me->getVar('defence_train') == $targetDefenceTrain ? "selected" : ""; ?>><?= formatDefenceTrain($targetDefenceTrain) ?>(훈사<?= $targetDefenceTrain ?>)</option>
<?php endforeach; ?>
<option value=999 <?= $me->getVar('defence_train') == 999 ? "selected" : ""; ?>><?= formatDefenceTrain(999) ?>[훈련, 사기 -3]</option>
<option value=999 <?= $me->getVar('defence_train') == 999 ? "selected" : ""; ?>><?= formatDefenceTrain(999) ?>
<?php if($changeDefence999Train != 0 || $changeDefence999Train != 0):
?>[<?=$changeDefence999Train!=0?"훈련 {$changeDefence999Train},":''?><?=$changeDefence999Atmos!=0?"사기 {$changeDefence999Atmos}":''
?>]<?php endif?></option>
</select>
】<br><br>
<input type=<?= $submit ?> id='set_my_setting' name=btn style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px; value=설정저장><br>
@@ -122,9 +150,19 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<!--빙의 해제용 삭턴 조절<br>
<a href="b_myPage.php?detachNPC=1"><button type="button" style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>빙의 해체 요청</button></a>-->
<?php if ($showDieImmediatelyBtn) : ?>
<?php if ($showDieOnPrestartBtn) : ?>
가오픈 기간 내 장수 삭제 (<?= substr($targetTime, 0, 19) ?> 부터)<br>
<a href="c_die_immediately.php" id='die_immediately'><button type="button" style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>장수 삭제</button></a><br><br>
<button type="button" id='dieOnPrestart' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>장수 삭제</button><br><br>
<?php endif; ?>
<?php if ($showBuildNationCandidateBtn) : ?>
서버 개시 이전 거병(2턴부터 건국 가능)<br>
<button type="button" id='buildNationCandidate' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>사전 거병</button><br><br>
<?php endif; ?>
<?php if (GameConst::$availableInstantAction['instantRetreat'] ?? false) : ?>
거리 3칸 이내 아국 도시로 즉시 이동<br>
<button type="button" id='instantRetreat' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>접경 귀환</button><br><br>
<?php endif; ?>
<?php if ($gameStor->npcmode == 2 && $me->getNPCType() == 0) : ?>
@@ -155,7 +193,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<div class="row mx-1">
<div class="btn-group" role="group">
<?php foreach ($me->getItems() as $itemKey => $item) : ?>
<button type="button" data-item-type='<?=$itemKey?>' class="drop-item-btn btn btn-primary <?= $item->getName() == '-' ? 'disabled' : '' ?>"><?= $item->getName() ?></button>
<button type="button" data-item-type='<?= $itemKey ?>' class="drop-item-btn btn btn-primary <?= $item->getName() == '-' ? 'disabled' : '' ?>"><?= $item->getName() ?></button>
<?php endforeach; ?>
</div>
</div>
@@ -166,7 +204,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
</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="col bg1 text-center">
<h4 style='color:skyblue'>개인 기록</h4>
@@ -179,7 +217,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>
</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="col bg1 text-center">
<h4 style='color:orange'>전투 기록</h4>
@@ -193,7 +231,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
</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="col bg1 text-center">
<h4 style='color:skyblue'>장수 열전</h4>
@@ -203,7 +241,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<?= formatHistoryToHTML(getGeneralHistoryLogAll($generalID)) ?>
</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="col bg1 text-center">
<h4 style='color:orange'>전투 결과</h4>
+77 -120
View File
@@ -14,13 +14,16 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("토너먼트", 1);
TurnExecutionHelper::executeAllCommand();
$me = $db->queryFirstRow('select no,tournament,con,turntime from general where owner=%i', $userID);
$generalID = $session->generalID;
$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
);
$generalID = $me['no'];
$admin = $gameStor->getValues(['tournament', 'phase', 'turnterm', 'tnmt_msg', 'tnmt_type', 'develcost', 'tnmt_trig']);
$turnTerm = $admin['turnterm'];
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_msg', 'tnmt_type', 'develcost', 'tnmt_trig']);
$con = checkLimit($me['con']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
printLimitMsg($me['turntime']);
exit();
}
@@ -99,16 +102,18 @@ $globalBetTotal = array_sum($globalBet);
?>
<!DOCTYPE html>
<html>
<?php if ($con == 1) {
<?php if ($limitState == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다! 제한량이 모자라다면 참여를 해보세요^^");
} ?>
<head>
<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" />
<title><?= UniqueConst::$serverName ?>: 토너먼트</title>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= 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>
@@ -120,128 +125,80 @@ $globalBetTotal = array_sum($globalBet);
</tr>
</table>
<table align=center class='tb_layout bg0'>
<?php
if ($session->userGrade >= 5) {
$sel = [];
echo "
<form method=post action=c_tournament.php>
<tr><td colspan=8><input type=textarea size=150 style=color:white;background-color:black; name=msg><input type=submit name=btn value='메시지'></td></tr>
<tr><td colspan=8>
<input type=button value='갱신' onclick='location.reload()'>";
<?php if ($session->userGrade >= 5) : ?>
<form method=post action=c_tournament.php>
<tr>
<td colspan=8><input type=textarea size=150 style=color:white;background-color:black; name=msg><input type=submit name=btn value='메시지'></td>
</tr>
<tr>
<td colspan=8>
<button type="button" class="btn btn-secondary" onclick='location.reload()'>갱신</button>
<?php if ($admin['tournament'] == 0) : ?>
<select name=trig size=1 style=color:white;background-color:black;>
<option style=color:white; value=0 <?= !$admin['tnmt_trig'] ? 'selected' : '' ?>>수동진행</option>
<option style=color:white; value=1 <?= $admin['tnmt_trig'] ? 'selected' : '' ?>>자동진행</option>
</select>
<input type=submit name=btn value='자동개최설정'>
<?php else : ?>
<input type=submit name=btn value='중단' onclick='return confirm("진짜 중단하시겠습니까?")'>
<?php endif; ?>
switch ($admin['tnmt_trig']) {
case 0:
$sel[0] = "selected";
break;
case 1:
$sel[1] = "selected";
break;
case 2:
$sel[2] = "selected";
break;
case 3:
$sel[3] = "selected";
break;
case 4:
$sel[4] = "selected";
break;
case 5:
$sel[5] = "selected";
break;
case 6:
$sel[6] = "selected";
break;
case 7:
$sel[7] = "selected";
break;
}
if ($admin['tournament'] == 0) {
?>
<select name=auto size=1 style=color:white;background-color:black;>
<option style=color:white; value=0>수동진행</option>
<option style=color:white; value=1>12분 05일</option>
<option style=color:white; value=2>07분 10시</option>
<option style=color:white; value=3>03분 04시</option>
<option style=color:white; value=4>01분 82분</option>
<option style=color:white; value=5>30초 41분</option>
<option style=color:white; value=6>15초 21분</option>
<option style=color:white; value=7>05초 07분</option>
</select>
<select name=type size=1 style=color:white;background-color:black;>
<option style=color:white; value=0>전력전</option>
<option style=color:white; value=1>통솔전</option>
<option style=color:white; value=2>일기토</option>
<option style=color:white; value=3>설전</option>
</select>
<input type=submit name=btn value='개최'>
<select name=trig size=1 style=color:white;background-color:black;>
<option style=color:white; value=0 <?= $sel[0] ?? '' ?>>수동진행</option>
<option style=color:white; value=1 <?= $sel[1] ?? '' ?>>12분 05일</option>
<option style=color:white; value=2 <?= $sel[2] ?? '' ?>>07분 10시</option>
<option style=color:white; value=3 <?= $sel[3] ?? '' ?>>03분 04시</option>
<option style=color:white; value=4 <?= $sel[4] ?? '' ?>>01분 82분</option>
<option style=color:white; value=5 <?= $sel[5] ?? '' ?>>30초 41분</option>
<option style=color:white; value=6 <?= $sel[6] ?? '' ?>>15초 21분</option>
<option style=color:white; value=7 <?= $sel[7] ?? '' ?>>05초 07분</option>
</select>
<input type=submit name=btn value='자동개최설정'>
<input type=submit name=btn value='포상'>
<input type=submit name=btn value='회수'>
<?php
} else {
echo "<input type=submit name=btn value='중단' onclick='return confirm(\"진짜 중단하시겠습니까?\")'>";
}
<?php switch ($admin['tournament']) {
case 1:
echo "<input type=submit name=btn value='랜덤투입'>";
echo "<input type=submit name=btn value='랜덤전부투입'>";
break;
case 2:
echo "<input type=submit name=btn value='예선'><input type=submit name=btn value='예선전부'>";
break;
case 3:
echo "<input type=submit name=btn value='추첨'><input type=submit name=btn value='추첨전부'>";
break;
case 4:
echo "<input type=submit name=btn value='본선'><input type=submit name=btn value='본선전부'>";
break;
case 5:
echo "<input type=submit name=btn value='배정'>";
break;
case 6:
echo "<input type=submit name=btn value='베팅마감'>";
break;
case 7:
echo "<input type=submit name=btn value='16강'>";
break;
case 8:
echo "<input type=submit name=btn value='8강'>";
break;
case 9:
echo "<input type=submit name=btn value='4강'>";
break;
case 10:
echo "<input type=submit name=btn value='결승'>";
break;
} ?>
switch ($admin['tournament']) {
case 1:
echo "<input type=submit name=btn value='랜덤투입'>";
echo "<input type=submit name=btn value='랜덤전부투입'>";
break;
case 2:
echo "<input type=submit name=btn value='예선'><input type=submit name=btn value='예선전부'>";
break;
case 3:
echo "<input type=submit name=btn value='추첨'><input type=submit name=btn value='추첨전부'>";
break;
case 4:
echo "<input type=submit name=btn value='본선'><input type=submit name=btn value='본선전부'>";
break;
case 5:
echo "<input type=submit name=btn value='배정'>";
break;
case 6:
echo "<input type=submit name=btn value='베팅마감'>";
break;
case 7:
echo "<input type=submit name=btn value='16강'>";
break;
case 8:
echo "<input type=submit name=btn value='8강'>";
break;
case 9:
echo "<input type=submit name=btn value='4강'>";
break;
case 10:
echo "<input type=submit name=btn value='결승'>";
break;
}
echo "
</td></tr>
</form>";
} elseif ($me['no'] > 0 && $me['tournament'] == 0 && $admin['tournament'] == 1) {
echo "<form method=post action=c_tournament.php><tr><td colspan=8><input type=button value='갱신' onclick='location.reload()'><input type=submit name=btn value='참가' onclick='return confirm(\"참가비 금{$admin['develcost']}이 필요합니다. 참가하시겠습니까?\")'></td></tr></form>";
} else {
echo "<tr><td colspan=8><input type=button value='갱신' onclick='location.reload()'></td></tr>";
}
</td>
</tr>
</form>
<?php elseif ($me['no'] > 0 && $me['tournament'] == 0 && $admin['tournament'] == 1) : ?>
<form method=post action=c_tournament.php>
<tr>
<td colspan=8><button type="button" class="btn btn-secondary" onclick='location.reload()'>갱신</button><button type="submit" class="btn btn-sammo-base2" onclick='return confirm("참가비 금<?= $admin['develcost'] ?>이 필요합니다. 참가하시겠습니까?")'>참가</button><input type='hidden' name='btn' value='참가'/></td>
</tr>
</form>
<?php else : ?>
<tr>
<td colspan=8><button type="button" class="btn btn-secondary" onclick='location.reload()'>갱신</button></td>
</tr>
<?php endif;
$str1 = getTournament($admin['tournament']);
$str2 = getTournamentTime();
if ($str2) {
$str2 = ', ' . $str2;
}
$str3 = getTournamentTermText();
$str3 = getTournamentTermText($turnTerm);
if ($str3) {
$str3 = ', ' . $str3;
}
-230
View File
@@ -1,230 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
increaseRefresh("부대편성", 1);
$me = $db->queryFirstRow('SELECT no,nation,troop FROM general WHERE owner=%i', $userID);
$troops = [];
foreach ($db->query('SELECT troop_leader,name FROM troop WHERE nation = %i', $me['nation']) as $rawTroop) {
$troops[$rawTroop['troop_leader']] = [
'name' => $rawTroop['name'],
'users' => []
];
}
foreach ($db->query(
'SELECT no,name,turntime,troop,city FROM general WHERE troop!=0 AND nation = %i ORDER BY turntime ASC',
$me['nation']
) as $general) {
if (!key_exists($general['troop'], $troops)) {
trigger_error("올바르지 않은 부대 소속 {$general['no']}, {$general['name']} : {$general['troop']}");
continue;
}
$general['cityText'] = CityConst::byID($general['city'])->name;
$troops[$general['troop']]['users'][] = $general;
}
if ($troops) {
$troopLeaders = $db->query(
'SELECT no,name,picture,imgsvr,turntime,city,troop FROM general WHERE no IN %li',
array_keys($troops)
);
$generalTurnList = [];
foreach ($db->queryAllLists(
'SELECT general_id, turn_idx, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id ASC, turn_idx ASC',
array_column($troopLeaders, 'no')
) as [$generalID, $turnIdx, $brief]) {
if (!key_exists($generalID, $generalTurnList)) {
$generalTurnList[$generalID] = [];
}
$generalTurnList[$generalID][$turnIdx] = $brief;
}
foreach ($troopLeaders as $troopLeader) {
$imageTemp = GetImageURL($troopLeader['imgsvr']);
$troopLeader['pictureFullPath'] = "$imageTemp/{$troopLeader['picture']}";
$troopLeader['cityText'] = CityConst::byID($troopLeader['city'])->name;
$turnText = [];
foreach ($generalTurnList[$troopLeader['no']] as $rawTurnIdx => $brief) {
if ($brief != '집합') {
$brief = '~';
}
$turnIdx = $rawTurnIdx + 1;
$turnText[] = "{$turnIdx} : {$brief}";
}
$troopLeader['turnText'] = join('<br>', $turnText);
$troops[$troopLeader['troop']]['leader'] = $troopLeader;
}
}
uasort($troops, function ($lhs, $rhs) {
return $lhs['leader']['turntime'] <=> $rhs['leader']['turntime'];
})
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 부대편성</title>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('ts', ['common', 'troop'], true) ?>
</head>
<body>
<div style="width:1000px;margin:auto;">
<table width=1000 class='tb_layout bg0'>
<tr>
<td>부 대 편 성<br><?= backButton() ?></td>
</tr>
</table>
<table id="troop_list" class='tb_layout bg0'>
<thead>
<tr>
<td width=64 class='bg1 center'>선 택</td>
<td width=130 class='bg1 center'>부 대 정 보</td>
<td width=100 class='bg1 center'>부 대 장</td>
<td width=576 class='bg1 center' style=table-layout:fixed;word-break:break-all;>장 수</td>
<td width=130 class='bg1 center' style=table-layout:fixed;word-break:break-all;>부대장행동</td>
</tr>
</thead>
<tfoot>
<tr>
<td colspan='5'>
<?php if (!$troops) : ?>
<?php elseif ($me['troop'] == 0) : ?>
<input type=button id='btnJoinTroop' value='부 대 가 입'>
<?php else : ?>
<input type=button id="btnLeaveTroop" value='부 대 탈 퇴'>
<?php endif; ?>
</td>
</tr>
</tfoot>
<tbody>
<?php
foreach ($troops as $troopNo => $troop) {
$troopLeader = $troop['leader'];
$genlistText = [];
$cityText = $troopLeader['cityText'];
$cityID = $troopLeader['city'];
$leaderID = $troopLeader['no'];
foreach ($troop['users'] as $troopUser) {
$spanClass = 'troopUser';
if ($troopUser['city'] !== $cityID) {
$spanClass .= ' diffCity';
}
if ($troopUser['no'] == $leaderID) {
$spanClass .= ' leader';
}
$genlistText[] = "<span class='$spanClass' data-general-id='{$troopUser['no']}'
><span class='generalName'>{$troopUser['name']}</span><span class='cityText'>【{$troopUser['cityText']}】</span
></span>";
}
$genlistText = sprintf('%s (%d명)', join(', ', $genlistText), count($genlistText)); ?>
<?php if ($me['troop'] == 0) : ?>
<tr>
<td align=center rowspan=2><input type='radio' class='troopId' name='troop' value='<?= $troopNo ?>'></td>
<td align=center><?= $troop['name'] ?><br>【 <?= $cityText ?> 】</td>
<td height=64 class='generalIcon' style='background:no-repeat center url("<?= $troopLeader['pictureFullPath'] ?>");background-size:64px;'>&nbsp;</td>
<td rowspan=2 width=62><?= $genlistText ?></td>
<td rowspan=2><?= $troopLeader['turnText'] ?></td>
</tr>
<tr>
<td align=center>
<font size=2>【턴】 <?= substr($troopLeader['turntime'], 14, 5) ?></font>
</td>
<td align=center>
<font size=1><?= $troopLeader['name'] ?></font>
</td>
</tr>
<tr>
<td colspan=5>
<?php else : ?>
<tr>
<td align=center rowspan=2>&nbsp;</td>
<td align=center><?= $troop['name'] ?><br>【 <?= $cityText ?> 】</td>
<td height=64 class='generalIcon' style='background:no-repeat center url("<?= $troopLeader['pictureFullPath'] ?>");background-size:64px;'>&nbsp;</td>
<td rowspan=2 width=62><?= $genlistText ?></td>
<td rowspan=2>
<?php if ($me['no'] == $troopLeader['no']) : ?>
<select id='genNo' name=gen size=3 style=color:white;background-color:black;font-size:14px;width:128px;>";
<?php foreach ($troop['users'] as $troopUser) : ?>
<?php if ($troopUser['no'] == $me['no']) {
continue;
} ?>
<option value='<?= $troopUser['no'] ?>'><?= $troopUser['name'] ?></option>
<?php endforeach; ?>
</select><br>
<input type=button id='btnKickTroop' value='부 대 추 방' style=width:130px;height:25px;>
<?php else : ?>
<?= $troopLeader['turnText'] ?>
<?php endif; ?>
</td>
</tr>
<tr>
<td align=center>
<font size=2>【턴】 <?= substr($troopLeader['turntime'], 14, 5) ?></font>
</td>
<td align=center>
<font size=1><?= $troopLeader['name'] ?></font>
</td>
</tr>
<tr>
<td colspan=5></td>
</tr>
<?php endif;
} //foreach ($troops as $troopNo=>$troop) {
?>
</tbody>
</table>
<br>
<table width=1000 class='tb_layout bg0'>
<tr>
<td width=80 class='bg1'>부 대 명</td>
<td width=130><input type=text style=color:white;background-color:black; size=18 maxlength=18 id='nameplate'></td>
<?php if ($me['troop'] == 0) : ?>
<td><input type=button id='btnCreateTroop' value='부 대 창 설'></td>
<?php else : ?>
<td><input type=button id='btnChangeTroopName' value='부 대 변 경'></td>
<?php endif; ?>
</tr>
</table>
<table width=1000 class='tb_layout bg0'>
<tr>
<td><?= backButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
</div>
</body>
</html>
+32 -3
View File
@@ -43,6 +43,7 @@ if ($nationID) {
<head>
<title><?= UniqueConst::$serverName ?>: 전투 시뮬레이터</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=1100" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
@@ -54,6 +55,7 @@ if ($nationID) {
var city = <?= Json::encode($city) ?>;
var nation = <?= Json::encode($nation) ?>;
</script>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common', 'battle_simulator']) ?>
</head>
@@ -64,8 +66,8 @@ if ($nationID) {
전역 설정
</div>
<div class="card-body dragpad_battle">
<div class="row">
<div class="col-sm-6">
<div class="row gx-0">
<div class="col-sm-4">
<div class="input-group">
<input type="number" class="form-control" aria-describedby="text_year" value="<?= $startYear ?>" disabled>
<div class="input-group-text"> 년 시작 </div>
@@ -75,9 +77,13 @@ if ($nationID) {
<div class="input-group-text"> 월 </div>
</div>
</div>
<div class="col-sm-6">
<div class="col-sm-5 px-2">
<div class="btn-toolbar" role="toolbar">
<div class="input-group me-2" role="group">
<div class="input-group-text">
시드
</div>
<input type="text" class="form-control" id="seed" aria-describedby="text_seed">
<div class="input-group-text">
반복 횟수
</div>
@@ -86,6 +92,10 @@ if ($nationID) {
<option value="1000">1000회 (요약 표기)</option>
</select>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="btn-toolbar" role="toolbar">
<div class="btn-group me-2" role="group">
<button type="button" class="btn btn-danger btn-begin_battle">전투</button>
</div>
@@ -425,6 +435,25 @@ if ($nationID) {
</div>
<input type="number" class="form-control form_killcrew" value="0" step="1">
</div>
<div class="input-group mb-0">
<div class="input-group-text">자신</div>
<div class="input-group-text">회피 확률</div>
<input type="number" class="form-control form_war_avoid_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">필살 확률</div>
<input type="number" class="form-control form_war_critical_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">계략 시도 확률</div>
<input type="number" class="form-control form_war_magic_trial_prob" value="0" step="1" min="0" max="5">
</div>
<div class="input-group mb-1">
<div class="input-group-text">상대</div>
<div class="input-group-text">회피 확률</div>
<input type="number" class="form-control form_oppose_war_avoid_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">필살 확률</div>
<input type="number" class="form-control form_oppose_war_critical_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">계략 시도 확률</div>
<input type="number" class="form-control form_oppose_war_magic_trial_prob" value="0" step="1" min="0" max="5">
</div>
</div>
</div>
+2 -2
View File
@@ -113,11 +113,11 @@ if($session->userGrade < 5) {
}
if($btn == "자동개최설정") {
$gameStor->tnmt_trig = $trig;
$gameStor->tnmt_trig = !!$trig;
} elseif($btn == "개최") {
startTournament($auto, $type);
} elseif($btn == "중단") {
$gameStor->tnmt_auto = 0;
$gameStor->tnmt_auto = false;
$gameStor->tournament = 0;
$gameStor->phase = 0;
} elseif($btn == "랜덤투입") {
+2 -7
View File
@@ -52,8 +52,8 @@ class DB
/**
* DB 객체 생성
*
* @return \MeekroDB
*
* @return \MeekroDB
* @suppress PhanTypeMismatchProperty
*/
public static function db()
@@ -61,11 +61,6 @@ class DB
if (self::$uDB === null) {
self::$uDB = new \MeekroDB(self::$host, self::$user, self::$password, self::$dbName, self::$port, self::$encoding);
self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
self::$uDB->error_handler = function () {
};
self::$uDB->throw_exception_on_error = true;
self::$uDB->throw_exception_on_nonsql_error = true;
}
return self::$uDB;
}
+53
View File
@@ -0,0 +1,53 @@
<?php
namespace sammo;
use sammo\DTO\MenuItem;
use sammo\DTO\MenuMulti;
use sammo\DTO\MenuSplit;
//변경을 원한다면 파일을 복제 후 수정
class GlobalMenu {
/** @var (MenuItem|MenuMulti|MenuSplit)[] */
const version = 3;
static ?array $menu = null;
public static function getMenu(): array{
if(static::$menu !== null){
return static::$menu;
}
static::$menu = [
new MenuItem('천통국 베팅', 'v_nationBetting.php', condHighlightVar: 'nationBetting'),
new MenuMulti('게임정보', [
new MenuItem('세력일람', 'a_kingdomList.php', newTab: true),
new MenuItem('장수일람', 'a_genList.php', newTab: true),
new MenuItem('명장일람', 'a_bestGeneral.php', newTab: true),
new MenuItem('명예의전당', 'a_hallOfFame.php', newTab: true),
new MenuItem('왕조일람', 'a_emperior.php', newTab: true),
]),
new MenuItem('연감', 'v_history.php', newTab: true),
new MenuSplit(
new MenuItem('게시판', '/board/community', newTab: true),
[
new MenuItem('건의/제안', '/board/request', newTab: true),
new MenuItem('팁/강좌', '/board/tip', newTab: true),
new MenuItem('패치 내역', '/board/patch', newTab: true),
]
),
new MenuSplit(
new MenuItem('공식 오픈 톡', 'https://open.kakao.com/o/', newTab: true),
[
new MenuItem('잡담 오픈 톡', 'https://open.kakao.com/o/', newTab: true)
],
),
new MenuItem('전투 시뮬레이터', 'battle_simulator.php', newTab: true),
new MenuMulti('기타 정보', [
new MenuItem('접속량정보', 'a_traffic.php', newTab: true),
new MenuItem('빙의일람', 'a_npcList', newTab: true, condShowVar: 'npcMode'),
]),
new MenuItem('설문조사', 'v_vote.php', newTab: true, condHighlightVar: 'vote'),
];
return static::$menu;
}
}
+6
View File
@@ -0,0 +1,6 @@
<?php
namespace sammo;
class ServerEnv extends ServerDefaultEnv {
//ServerEnv 기본값을 변경하고 싶다면 orig를 제거한 복사본을 만들고 수정
}
+116 -186
View File
@@ -5,9 +5,11 @@ namespace sammo;
use DateTime;
use Ds\Set;
use sammo\Enums\AuctionType;
use sammo\Enums\GeneralAccessLogColumn;
use sammo\Enums\GeneralColumn;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn;
use sammo\Event\Action;
require_once 'process_war.php';
require_once 'func_gamerule.php';
@@ -104,10 +106,9 @@ function GetImageURL($imgsvr, $filepath = '')
}
/**
* @param null|int $con 장수의 벌점
* @param null|int $conlimit 최대 벌점
* @param null|int $refreshScore 장수의 벌점
*/
function checkLimit($con = null)
function checkLimit($refreshScore = null)
{
$session = Session::getInstance();
if ($session->userGrade >= 4) {
@@ -117,15 +118,15 @@ function checkLimit($con = null)
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if ($con === null) {
$con = $db->queryFirstField('SELECT con FROM general WHERE `owner`=%i', Session::getUserID());
if ($refreshScore === null) {
$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;
//접속제한 90%이면 경고문구
} elseif ($con > $conlimit * 0.9) {
} elseif ($refreshScore > $refreshLimit * 0.9) {
return 1;
} else {
return 0;
@@ -148,7 +149,7 @@ function getRandGenName(RandUtil $rng)
function cityInfo(General $generalObj)
function cityInfo(GeneralLite $generalObj)
{
$db = DB::db();
@@ -643,7 +644,7 @@ function generalInfo(General $generalObj)
$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
? "{$generalObj->getVar('specage')}세"
: "<font color=limegreen>" . displayiActionObjInfo($generalObj->getSpecialDomestic()) . "</font>";
@@ -752,7 +753,7 @@ function generalInfo(General $generalObj)
<td style='text-align:center;' class='bg1'><b>부대</b></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;' 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>
</table>";
}
@@ -886,7 +887,7 @@ function generalInfo2(General $generalObj)
function getOnlineNum(): int
{
return KVStorage::getStorage(DB::db(), 'game_env')->getValue('online') ?? 0;
return KVStorage::getStorage(DB::db(), 'game_env')->getValue('online_user_cnt') ?? 0;
}
function onlinegen(General $general)
@@ -906,7 +907,7 @@ function nationMsg(General $general)
$nationID = $general->getNationID();
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
return $nationStor->notice ?? '';
return $nationStor->nationNotice['msg'] ?? '';
}
function banner()
@@ -999,76 +1000,69 @@ function increaseRefresh($type = "", $cnt = 1)
$generalID = $session->generalID;
$userGrade = $session->userGrade;
$date = TimeUtil::now();
$dateObj = new \DateTimeImmutable();
$date = TimeUtil::format($dateObj, false);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->refresh = $gameStor->refresh + $cnt; //TODO: +로 증가하는 값은 별도로 분리
$isunited = $gameStor->isunited;
$opentime = $gameStor->opentime;
if ($isunited != 2 && $generalID && $userGrade < 6 && $opentime <= TimeUtil::now()) {
$db->update('general', [
'lastrefresh' => $date,
'con' => $db->sqleval('con + %i', $cnt),
'connect' => $db->sqleval('connect + %i', $cnt),
'refcnt' => $db->sqleval('refcnt + %i', $cnt),
'refresh' => $db->sqleval('refresh + %i', $cnt)
], 'owner=%i', $userID);
if ($userGrade == 6) {
return;
}
if ($isunited == 2) {
return;
}
if (!$generalID) {
return;
}
if ($opentime > $date) {
return;
}
$date = date('Y_m_d H:i:s');
$date2 = substr($date, 0, 10);
$online = getOnlineNum();
file_put_contents(
__DIR__ . "/logs/" . UniqueConst::$serverID . "/_{$date2}_refresh.txt",
sprintf(
"%s, %s, %s, %s, %s, %d\n",
$date,
$session->userName,
$session->generalName,
$session->ip,
$type,
$online
),
FILE_APPEND
);
$gameStor->refresh = $gameStor->refresh + $cnt; //TODO: +로 증가하는 값은 별도로 분리
$proxy_headers = array(
'HTTP_VIA',
'HTTP_X_FORWARDED_FOR',
'HTTP_FORWARDED_FOR',
'HTTP_X_FORWARDED',
'HTTP_FORWARDED',
'HTTP_CLIENT_IP',
'HTTP_FORWARDED_FOR_IP',
'VIA',
'X_FORWARDED_FOR',
'FORWARDED_FOR',
'X_FORWARDED',
'FORWARDED',
'CLIENT_IP',
'FORWARDED_FOR_IP',
'HTTP_PROXY_CONNECTION'
);
$db->insertUpdate('general_access_log', [
GeneralAccessLogColumn::generalID->value => $generalID,
GeneralAccessLogColumn::userID->value => $userID,
GeneralAccessLogColumn::lastRefresh->value => $date,
GeneralAccessLogColumn::refreshTotal->value => $cnt,
GeneralAccessLogColumn::refresh->value => $cnt,
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),
]);
$str = "";
foreach ($proxy_headers as $x) {
if (isset($_SERVER[$x])) $str .= "//{$x}:{$_SERVER[$x]}";
}
if ($str != "") {
file_put_contents(
__DIR__ . "/logs/" . UniqueConst::$serverID . "/_{$date2}_ipcheck.txt",
sprintf(
"%s, %s, %s%s\n",
$session->userName,
$session->generalName,
$_SERVER['REMOTE_ADDR'],
$str
),
FILE_APPEND
);
}
$serverPath = __DIR__;
$serverID = UniqueConst::$serverID;
$logPath = "{$serverPath}/logs/{$serverID}/api_log.db";
$logDB = FileDB::db($logPath, $serverPath . '/../f_install/sql/api_log.sql');
$ip = $_SERVER['REMOTE_ADDR'] ?? 'local';
$date = date('Y-m-d H:i:s');
$logDB->insert('api_log', [
'user_id' => $session->userID,
'ip' => $ip,
'date' => $date,
'path' => "refresh",
'arg' => JSON::encode([
'type' => $type,
]),
'aux' => JSON::encode([
'generalID' => $generalID,
'generalName' => $session->generalName,
'userName' => $session->userName,
]),
]);
}
function updateTraffic()
@@ -1076,12 +1070,9 @@ function updateTraffic()
$online = getOnlineNum();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxonline', 'maxrefresh']);
$admin = $gameStor->getValues(['year', 'month', 'refresh', 'maxonline', 'maxrefresh', 'recentTraffic']);
/** @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']) {
$admin['maxrefresh'] = $admin['refresh'];
}
@@ -1092,22 +1083,20 @@ function updateTraffic()
$gameStor->maxrefresh = $admin['maxrefresh'];
$gameStor->maxonline = $admin['maxonline'];
$db->update('general', ['refresh' => 0], true);
$recentTraffic = $admin['recentTraffic'] ?? [];
if(count($recentTraffic) >= 5){
array_shift($recentTraffic);
}
$recentTraffic[] = [
'year'=>$admin['year'],
'month' => $admin['month'],
'refresh' => $admin['refresh'],
'online' => $online,
'date' => TimeUtil::now(),
];
$gameStor->recentTraffic = $recentTraffic;
$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
);
$db->update('general_access_log', ['refresh' => 0], true);
}
function CheckOverhead()
@@ -1115,13 +1104,13 @@ function CheckOverhead()
//서버정보
$db = DB::db();
$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) {
$gameStor->conlimit = $con;
if ($nextRefreshLimit != $refreshLimit) {
$gameStor->refreshLimit = $nextRefreshLimit;
}
}
@@ -1223,10 +1212,18 @@ function updateOnline()
$nationname[$nation['nation']] = $nation['name'];
}
//동접수
$before5Min = TimeUtil::nowAddMinutes(-5);
$onlineUser = $db->query('SELECT no,name,nation FROM general WHERE lastrefresh > %s AND npc < 2', $before5Min);
$startTurn = cutTurn($gameStor->turntime, $gameStor->turnterm, false);
$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);
$onlineNationUsers = Util::arrayGroupBy($onlineUser, 'nation');
@@ -1249,76 +1246,6 @@ function updateOnline()
$gameStor->online_nation = join(', ', $onlineNation);
}
function addAge(RandUtil $rng)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
//나이와 호봉 증가
$db->update('general', [
'age' => $db->sqleval('age+1'),
], true);
$db->update('general', [
'belong' => $db->sqleval('belong+1')
], 'nation != 0');
[$startYear, $year, $month] = $gameStor->getValuesAsArray(['startyear', 'year', 'month']);
if ($year >= $startYear + 3) {
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,aux from general where specage<=age and special=%s', GameConst::$defaultSpecialDomestic) as $general) {
$generalID = $general['no'];
$special = SpecialityHelper::pickSpecialDomestic(
$rng,
$general,
(Json::decode($general['aux'])['prev_types_special']) ?? []
);
$specialClass = buildGeneralSpecialDomesticClass($special);
$specialText = $specialClass->getName();
$db->update('general', [
'special' => $special
], 'no=%i', $generalID);
$logger = new ActionLogger($generalID, $general['nation'], $year, $month);
$josaUl = JosaUtil::pick($specialText, '을');
$logger->pushGeneralActionLog("특기 【<b><L>{$specialText}</></b>】{$josaUl} 익혔습니다!", ActionLogger::PLAIN);
$logger->pushGeneralHistoryLog("특기 【<b><C>{$specialText}</></b>】{$josaUl} 습득");
}
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,npc,dex1,dex2,dex3,dex4,dex5,aux from general where specage2<=age and special2=%s', GameConst::$defaultSpecialWar) as $general) {
$generalID = $general['no'];
$generalAux = Json::decode($general['aux']);
$updateVars = [];
if (key_exists('inheritSpecificSpecialWar', $generalAux)) {
$special2 = $generalAux['inheritSpecificSpecialWar'];
unset($generalAux['inheritSpecificSpecialWar']);
$updateVars['aux'] = Json::encode($generalAux);
} else {
$special2 = SpecialityHelper::pickSpecialWar(
$rng,
$general,
($generalAux['prev_types_special2']) ?? []
);
}
$specialClass = buildGeneralSpecialWarClass($special2);
$specialText = $specialClass->getName();
$updateVars['special2'] = $special2;
$db->update('general', $updateVars, 'no=%i', $general['no']);
$logger = new ActionLogger($generalID, $general['nation'], $year, $month);
$josaUl = JosaUtil::pick($specialText, '을');
$logger->pushGeneralActionLog("특기 【<b><L>{$specialText}</></b>】{$josaUl} 익혔습니다!", ActionLogger::PLAIN);
$logger->pushGeneralHistoryLog("특기 【<b><C>{$specialText}</></b>】{$josaUl} 습득");
}
}
}
function turnDate($curtime)
{
$db = DB::db();
@@ -1358,7 +1285,7 @@ function triggerTournament(RandUtil $rng)
if ($tournament != 0) {
return;
}
if ($tnmt_trig == 0) {
if (!$tnmt_trig) {
return;
}
if (!$rng->nextBool(0.4)) {
@@ -1374,7 +1301,7 @@ function triggerTournament(RandUtil $rng)
$tnmt_type = array_pop($tnmt_pattern);
$gameStor->setValue('tnmt_pattern', $tnmt_pattern);
startTournament($tnmt_trig, $tnmt_type);
startTournament($tnmt_type);
}
function CheckHall($no)
@@ -1410,7 +1337,7 @@ function CheckHall($no)
["betrate", 'calc'],
];
$generalObj = General::createGeneralObjFromDB($no, null, 2);
$generalObj = General::createObjFromDB($no);
$ttw = $generalObj->getRankVar(RankColumn::ttw);
$ttd = $generalObj->getRankVar(RankColumn::ttd);
@@ -1745,7 +1672,8 @@ function tryUniqueItemLottery(RandUtil $rng, General $general, string $acquireTy
$prob = 1 / ($genCount * $itemTypeCnt / 10 / 4); // 건국시 4개(20%) 등장(200명시 20국 정도 됨)
}
$prob = Util::valueFit($prob, null, 1 / 4); //최대치 감소
$prob *= GameConst::$uniqueTrialCoef;
$prob = Util::valueFit($prob, null, GameConst::$maxUniqueTrialProb); //최대치 감소
$result = false;
$prob /= sqrt(7);
@@ -1799,22 +1727,21 @@ function deleteNation(General $lord, bool $applyDB): array
$logger->pushGlobalHistoryLog("<R><b>【멸망】</b></><D><b>{$nationName}</b></>{$josaUn} <R>멸망</>했습니다.");
$nationGeneralList = General::createGeneralObjListFromDB(
$nationGeneralList = General::createObjListFromDB(
$db->queryFirstColumn(
'SELECT `no` FROM general WHERE nation=%i AND no != %i',
$nationID,
$lordID
),
['npc', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'],
1
['npc', 'owner', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'],
);
$nationGeneralList[$lordID] = $lord;
$nation['generals'] = array_keys($nationGeneralList);
$nation['aux'] = Json::decode($nation['aux']);
$nation['msg'] = $nationStor->notice;
$nation['msg'] = $nationStor->nationNotice['msg'] ?? '';
$nation['scout_msg'] = $nationStor->scout_msg;
$nation['aux'] += $nationStor->max_power;
$nation['aux'] += $nationStor->max_power ?? [];
$nation['history'] = getNationHistoryLogAll($nationID);
$josaYi = JosaUtil::pick($nationName, '이');
@@ -1823,13 +1750,16 @@ function deleteNation(General $lord, bool $applyDB): array
// 전 장수 재야로
foreach ($nationGeneralList as $general) {
$general->setAuxVar(
InheritanceKey::max_belong->value,
max(
$general->getVar('belong'),
$general->getAuxVar(InheritanceKey::max_belong->value) ?? 0
)
);
if ($general->getNPCType() < 2) {
$general->setAuxVar(
InheritanceKey::max_belong->value,
max(
$general->getVar('belong'),
$general->getAuxVar(InheritanceKey::max_belong->value) ?? 0
)
);
}
$general->setVar('belong', 0);
$general->setVar('troop', 0);
$general->setVar('officer_level', 0);
+2 -2
View File
@@ -18,7 +18,7 @@ function registerAuction(RandUtil $rng)
[AuctionType::BuyRice->value, AuctionType::SellRice->value],
));
$neutralbuyRiceCnt = $neutralAuctionCnt[AuctionType::BuyRice->value];
$neutralbuyRiceCnt = $neutralAuctionCnt[AuctionType::BuyRice->value] ?? 0;
// 판매건 등록
if ($rng->nextBool(1 / ($neutralbuyRiceCnt + 5))) {
@@ -38,7 +38,7 @@ function registerAuction(RandUtil $rng)
AuctionBuyRice::openResourceAuction($dummyGeneral, $amount, $term, $cost, $topv);
}
$neutralSellRiceCnt = $neutralAuctionCnt[AuctionType::SellRice->value];
$neutralSellRiceCnt = $neutralAuctionCnt[AuctionType::SellRice->value] ?? 0;
// 구매건 등록
if ($rng->nextBool(1 / ($neutralSellRiceCnt + 5))) {
//평균 쌀의 5% ~ 25%
+2 -2
View File
@@ -350,7 +350,7 @@ function setGeneralCommand(int $generalID, array $rawTurnList, string $command,
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($generalID);
$general = General::createObjFromDB($generalID);
try{
$commandObj = buildGeneralCommandClass($command, $general, $env, $arg);
@@ -425,7 +425,7 @@ function setNationCommand(int $generalID, array $turnList, string $command, ?arr
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($generalID);
$general = General::createObjFromDB($generalID);
if($general->getVar('officer_level') < 5){
return [
+84 -12
View File
@@ -133,19 +133,19 @@ function getNationType(?string $type) {
}
function getConnect($con) {
if($con < 50) $conname = '안함';
elseif($con < 100) $conname = '무관심';
elseif($con < 200) $conname = '가끔';
elseif($con < 400) $conname = '보통';
elseif($con < 800) $conname = '자주';
elseif($con < 1600) $conname = '열심';
elseif($con < 3200) $conname = '중독';
elseif($con < 6400) $conname = '폐인';
elseif($con < 12800) $conname = '경고';
else $conname = '헐...';
function getRefreshScoreText($score) {
if($score < 50) $scoreName = '안함';
elseif($score < 100) $scoreName = '무관심';
elseif($score < 200) $scoreName = '가끔';
elseif($score < 400) $scoreName = '보통';
elseif($score < 800) $scoreName = '자주';
elseif($score < 1600) $scoreName = '열심';
elseif($score < 3200) $scoreName = '중독';
elseif($score < 6400) $scoreName = '폐인';
elseif($score < 12800) $scoreName = '경고';
else $scoreName = '헐...';
return $conname;
return $scoreName;
}
function getNationType2(?string $type) {
@@ -256,6 +256,41 @@ function buildItemClass(?string $type):BaseItem{
return $obj;
}
function getScenarioEffectClass(?string $type){
if($type === null || $type === ''){
$type = 'None';
}
static $basePath = __NAMESPACE__.'\\ActionScenarioEffect\\';
$classPath = ($basePath.$type);
if(class_exists($classPath)){
return $classPath;
}
$classPath = ($basePath.'che_'.$type);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$type}은 시나리오 효과 클래스가 아님");
}
function buildScenarioEffectClass(?string $type):iAction{
static $cache = [];
if($type === null){
$type = 'None';
}
if(key_exists($type, $cache)){
return $cache[$type];
}
$class = getScenarioEffectClass($type);
$obj = new $class();
$cache[$type]= $obj;
return $obj;
}
function getGeneralSpecialDomesticClass(?string $type){
if($type === null || $type === ''){
$type = GameConst::$defaultSpecialDomestic;
@@ -326,6 +361,41 @@ function buildGeneralSpecialWarClass(?string $type):BaseSpecial{
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){
if($type === null || $type === ''){
$type = '휴식';
@@ -542,6 +612,8 @@ function getExpLevel($experience) {
$level = Util::toInt(sqrt($experience/10));
}
$level = Util::clamp($level, 0, GameConst::$maxLevel);
return $level;
}
+57 -339
View File
@@ -2,6 +2,9 @@
namespace sammo;
use sammo\DTO\AuctionInfo;
use sammo\Enums\AuctionType;
use sammo\Enums\EventTarget;
use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn;
@@ -182,27 +185,6 @@ function updateGeneralNumber()
refreshNationStaticInfo();
}
function updateYearly()
{
//통계
checkStatistic();
}
//관직 변경 해제
function updateQuaterly()
{
$db = DB::db();
//천도 제한 해제, 관직 변경 제한 해제
$db->update('nation', [
'chief_set' => 0,
], true);
//관직 변경 제한 해제
$db->update('city', [
'officer_set' => 0,
], true);
}
// 벌점 감소와 건국제한-1 전턴제한-1 외교제한-1, 1달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정
function preUpdateMonthly()
{
@@ -218,62 +200,12 @@ function preUpdateMonthly()
$admin = $gameStor->getValues(['startyear', 'year', 'month']);
$logger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//보급선 체크
checkSupply();
//미보급도시 10% 감소
$db->update('city', [
'pop' => $db->sqleval('pop * 0.9'),
'trust' => $db->sqleval('trust * 0.9'),
'agri' => $db->sqleval('agri * 0.9'),
'comm' => $db->sqleval('comm * 0.9'),
'secu' => $db->sqleval('secu * 0.9'),
'def' => $db->sqleval('def * 0.9'),
'wall' => $db->sqleval('wall * 0.9'),
], 'supply = 0');
//미보급도시 장수 병 훈 사 5%감소
//NOTE: update inner join도 가능하지만, meekrodb 기준으로 깔끔하게.
$unsuppliedCities = $db->query('SELECT city, nation, trust, name FROM city WHERE supply = 0');
foreach (Util::arrayGroupBy($unsuppliedCities, 'nation') as $nationID => $cityList) {
$cityIDList = Util::squeezeFromArray($cityList, 'city');
$db->update('general', [
'crew' => $db->sqleval('crew*0.95'),
'atmos' => $db->sqleval('atmos*0.95'),
'train' => $db->sqleval('train*0.95'),
], 'city IN %li AND nation = %i', $cityIDList, $nationID);
}
//민심30이하 공백지 처리
$lostCities = [];
foreach ($unsuppliedCities as $unsuppliedCity) {
if ($unsuppliedCity['trust'] >= 30) {
continue;
}
$lostCities[$unsuppliedCity['city']] = $unsuppliedCity;
}
if ($lostCities) {
foreach ($lostCities as $lostCity) {
$josaYi = JosaUtil::pick($lostCity['name'], '이');
$logger->pushGlobalHistoryLog("<R><b>【고립】</b></><G><b>{$lostCity['name']}</b></>{$josaYi} 보급이 끊겨 <R>미지배</> 도시가 되었습니다.");
}
$db->update('general', [
'officer_level' => 1,
'officer_city' => 0
], 'officer_city IN %li', array_keys($lostCities));
$db->update('city', [
'nation' => 0,
'officer_set' => 0,
'conflict' => '{}',
'term' => 0,
'front' => 0
], 'city IN %li', array_keys($lostCities));
}
//접률감소, 건국제한-1
$db->update('general_access_log', [
'refresh_score_total' => $db->sqleval('floor(refresh_score_total*0.99)'),
], true);
$db->update('general', [
'connect' => $db->sqleval('floor(connect*0.99)'),
'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'),
], true);
//전략제한-1, 외교제한-1, 세율동기화
@@ -283,18 +215,10 @@ function preUpdateMonthly()
'rate_tmp' => $db->sqleval('rate')
], true);
//도시훈사 180년 60, 220년 87, 240년 100
$rate = Util::round(($admin['year'] - $admin['startyear']) / 1.5) + 60;
if ($rate > 100) $rate = 100;
// 20 ~ 140원
$develcost = ($admin['year'] - $admin['startyear'] + 10) * 2;
$gameStor->city_rate = $rate;
$gameStor->develcost = $develcost;
//매달 사망자 수입 결산
processWarIncome();
//계략, 전쟁표시 해제
$db->update('city', [
'state' => $db->sqleval(<<<EOD
@@ -379,7 +303,6 @@ function postUpdateMonthly(RandUtil $rng)
WHERE g.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(avg(connect)) from general where nation=A.nation)
)/10)
as power,
(select sum(crew) from general where nation=A.nation) as totalCrew
@@ -501,8 +424,6 @@ function postUpdateMonthly(RandUtil $rng)
if ($admin['year'] >= $admin['startyear'] + 2) {
checkWander($rng);
}
// 작위 업데이트
updateNationState();
updateGeneralNumber();
refreshNationStaticInfo();
// 천통여부 검사
@@ -526,11 +447,11 @@ function checkWander(RandUtil $rng)
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month']);
$admin = $gameStor->getValues(['year', 'month', 'init_year', 'init_month']);
$wanderers = $db->queryFirstColumn('SELECT general.`no` FROM general LEFT JOIN nation ON general.nation = nation.nation WHERE nation.`level` = 0 AND general.`officer_level` = 12');
foreach (General::createGeneralObjListFromDB($wanderers) as $wanderer) {
foreach (General::createObjListFromDB($wanderers) as $wanderer) {
$wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin);
if ($wanderCmd->hasFullConditionMet()) {
$logger = $wanderer->getLogger();
@@ -545,248 +466,6 @@ function checkWander(RandUtil $rng)
}
}
function updateNationState()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$history = array();
$admin = $gameStor->getValues(['killturn', 'year', 'month', 'fiction', 'startyear', 'show_img_level', 'turnterm', 'turntime']);
$year = $admin['year'];
$month = $admin['month'];
$startYear = $admin['startyear'];
$assemblerCnts = [];
foreach ($db->queryAllLists('SELECT nation,count(no) FROM general WHERE npc = 5 GROUP BY nation') as [$nationID, $assemblerCnt]) {
$assemblerCnts[$nationID] = $assemblerCnt;
};
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
//TODO: level이 진관수이소중대특 체계를 벗어날 수 있음
$nationID = $nation['nation'];
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nationID);
if ($citycount == 0) {
$nationlevel = 0; // 방랑군
} elseif ($citycount == 1) {
$nationlevel = 1; // 호족
} elseif ($citycount <= 4) {
$nationlevel = 2; // 군벌
} elseif ($citycount <= 7) {
$nationlevel = 3; // 주자사
} elseif ($citycount <= 10) {
$nationlevel = 4; // 주목
} elseif ($citycount <= 15) {
$nationlevel = 5; // 공
} elseif ($citycount <= 20) {
$nationlevel = 6; // 왕
} else {
$nationlevel = 7; // 황제
}
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),
];
switch ($nationlevel) {
case 7:
$josaUl = JosaUtil::pick(getNationLevel($nationlevel), '을');
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭"]);
$auxVal = Json::decode($nation['aux']);
$auxVal['can_국기변경'] = 1;
$auxVal['can_국호변경'] = 1;
$updateVals['aux'] = Json::encode($auxVal);
break;
case 6:
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]);
break;
case 5:
case 4:
case 3:
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명됨"]);
break;
case 2:
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>로 나서다"]);
break;
}
$db->update('nation', $updateVals, 'nation=%i', $nation['nation']);
$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);
}
}
}
$assemblerCnt = $assemblerCnts[$nation['nation']] ?? 0;
$maxAssemblerCnt = [
1 => 0,
2 => 1,
3 => 3,
4 => 4,
5 => 6,
6 => 7,
7 => 9
][$nationlevel] ?? 0;
if ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID = $gameStor->assembler_id ?? 0;
$troopLeaderRng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'troopLeader',
$year,
$month,
$nationID
)));
while ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID += 1;
$npcObj = new Scenario\GeneralBuilder(
$troopLeaderRng,
sprintf('부대장%4d', $lastAssemblerID),
false,
null,
$nation['nation']
);
$npcObj->setAffinity(999)->setStat(10, 10, 10)
->setSpecialSingle('척사')->setEgo('che_은둔')
->setKillturn(70)->setGoldRice(0, 0)
->setNPCType(5)->fillRemainSpecAsZero($admin);
$npcObj->build($admin);
$npcID = $npcObj->getGeneralID();
$db->insert('troop', [
'troop_leader' => $npcID,
'name' => $npcObj->getGeneralName(),
'nation' => $nation['nation'],
]);
$db->update('general', [
'troop' => $npcID
], 'no=%i', $npcID);
$cmd = buildGeneralCommandClass('che_집합', General::createGeneralObjFromDB($npcID), $admin);
_setGeneralCommand($cmd, iterator_to_array(Util::range(GameConst::$maxTurn)));
$assemblerCnt += 1;
$gameStor->assembler_id = $lastAssemblerID;
}
}
}
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
}
function checkStatistic()
{
$db = DB::db();
@@ -1019,7 +698,7 @@ function checkEmperior()
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']);
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'refreshLimit']);
if ($admin['isunited'] != 0) {
return;
}
@@ -1053,8 +732,18 @@ function checkEmperior()
$nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']);
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
/** @var int[] */
$auctionList = $db->queryFirstColumn(
'SELECT `id` FROM `ng_auction` WHERE `type` = %s AND `finished` = 0 ORDER BY `close_date` ASC',
AuctionType::UniqueItem->value
);
foreach($auctionList as $auctionID){
$auction = new AuctionUniqueItem($auctionID, new DummyGeneral(true));
$auction->closeAuction(true);
}
$inheritPointManager = InheritancePointManager::getInstance();
$allUserGenerals = General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc < 2'));
$allUserGenerals = General::createObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc < 2'));
foreach ($allUserGenerals as $genObj) {
if ($genObj->getNationID() == $nationID) {
if ($genObj->getVar('officer_level') > 4) {
@@ -1062,15 +751,16 @@ function checkEmperior()
};
}
}
processSumInheritPointRank();
TurnExecutionHelper::runEventHandler($db, $gameStor, EventTarget::United);
foreach ($allUserGenerals as $genObj) {
$inheritPointManager->mergeTotalInheritancePoint($genObj, true);
$inheritPointManager->mergeTotalInheritancePoint($genObj);
$inheritPointManager->applyInheritanceUser($genObj->getVar('owner'));
$inheritPointManager->clearInheritancePoint($genObj);
}
$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) {
CheckHall($hallGeneralNo);
@@ -1082,7 +772,7 @@ function checkEmperior()
$chiefs = Util::convertArrayToDict(
$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
),
'officer_level'
@@ -1135,9 +825,9 @@ function checkEmperior()
$nation = $nation;
$nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']);
$nation['aux'] = Json::decode($nation['aux']);
$nation['msg'] = $nationStor->notice;
$nation['msg'] = $nationStor->nationNotice['msg'] ?? '';;
$nation['scout_msg'] = $nationStor->scout_msg;
$nation['aux'] += $nationStor->max_power;
$nation['aux'] += $nationStor->max_power ?? [];
$nation['history'] = getNationHistoryLogAll($nation['nation']);
storeOldGenerals(0, $admin['year'], $admin['month']);
@@ -1214,11 +904,39 @@ function checkEmperior()
]);
$hiddenSeed = UniqueConst::$hiddenSeed;
$history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다. <span class='hidden_but_copyable'>(서버시드: $hiddenSeed})</span>"];
$history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다. <span class='hidden_but_copyable'>(서버시드: {$hiddenSeed})</span>"];
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
//연감 월결산
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)
+10
View File
@@ -254,6 +254,7 @@ function pushGeneralHistoryLog(int $generalID, ?array $history, $year=null, $mon
}
/** @deprecated */
function getGeneralHistoryLogAll(int $generalID):array {
$db = DB::db();
@@ -263,6 +264,15 @@ function getGeneralHistoryLogAll(int $generalID):array {
);
}
function getGeneralHistoryLogWithLogID(int $generalID):array {
$db = DB::db();
return Util::convertPairArrayToDict($db->queryAllLists(
'SELECT `id`, `text` from general_record WHERE general_id = %i AND log_type = "history" order by id desc',
$generalID
));
}
function pushNationHistoryLog(int $nationID, ?array $history, ?int $year=null, ?int $month=null) {
if(!$history){
+6
View File
@@ -12,6 +12,7 @@ function printLimitMsg($turntime)
<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') ?>
@@ -118,6 +119,11 @@ function backButton()
return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('./')>돌아가기</button><br>";
}
function gatewayButton()
{
return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('../')>돌아가기</button><br>";
}
function CoreBackButton()
{
return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('v_chiefCenter.php')>돌아가기</button><br>";
+1
View File
@@ -25,6 +25,7 @@ function requireAdminPermissionHTML()
<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') ?>
+25 -283
View File
@@ -4,173 +4,32 @@ namespace sammo;
use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn;
use Ds\Map;
use sammo\Enums\ResourceType;
use sammo\Event\Action;
/**
* 시간 단위로 일어나는 이벤트들에 대한 함수 모음
*/
/** @deprecated */
function processSumInheritPointRank(){
$db = DB::db();
$generals = General::createGeneralObjListFromDB(null, null, 2);
$points = new Map();
$points->allocate(count($generals));
foreach($generals as $general){
$generalID = $general->getID();
$points[$generalID] = 0;
}
foreach(InheritanceKey::cases() as $key){
if($key === InheritanceKey::previous){
continue;
}
$subPoints = InheritancePointManager::getInstance()->getInheritancePointFromAll($generals, $key);
foreach($generals as $general){
$generalID = $general->getID();
$points[$generalID] += $subPoints[$generalID] ?? 0;
}
}
$pointsPairs = [];
foreach($points as $generalID => $point){
$pointsPairs[] = [
'nation_id' => $generals[$generalID]->getNationID(),
'general_id' => $generalID,
'type' => RankColumn::inherit_point_earned_by_merge->value,
'value' => $point,
];
}
//XXX: multiple batch update가 제공되지 않으므로..
$db->delete('rank_data', '`type` = %s', RankColumn::inherit_point_earned_by_merge->value);
$db->insert('rank_data', $pointsPairs);
$db->query(
'UPDATE `rank_data` D SET `value` = (SELECT SUM(`value`) FROM `rank_data` S WHERE S.general_id = D.general_id AND S.`type` IN %ls) WHERE D.`type` = %s',
[RankColumn::inherit_point_earned_by_action->value, RankColumn::inherit_point_earned_by_merge->value],
RankColumn::inherit_point_earned->value
);
$db->query(
'UPDATE `rank_data` D SET `value` = (SELECT `value` FROM `rank_data` S WHERE S.general_id = D.general_id AND S.`type` = %s) WHERE D.`type` = %s',
RankColumn::inherit_point_spent_dynamic->value,
RankColumn::inherit_point_spent->value
);
}
//1월마다 실행
function processSpring() {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
// 1월엔 무조건 내정 1% 감소
$db->update('city',[
'dead'=>0,
'agri'=>$db->sqleval('agri * 0.99'),
'comm'=>$db->sqleval('comm * 0.99'),
'secu'=>$db->sqleval('secu * 0.99'),
'def'=>$db->sqleval('def * 0.99'),
'wall'=>$db->sqleval('wall * 0.99'),
],true);
//인구 증가
popIncrease();
// > 10000 유지비 3%, > 1000 유지비 1%
// 유지비 1%
$db->update('general', [
'gold'=>$db->sqleval('IF(gold > 10000, gold * 0.97, gold * 0.99)')
], 'gold > 1000');
// > 100000 유지비 5%, > 100000 유지비 3%, > 1000 유지비 1%
$db->update('nation', [
'gold'=>$db->sqleval('IF(gold > 100000, gold * 0.95, IF(gold > 10000, gold * 0.97, gold * 0.99))')
], 'gold > 1000');
$admin = $gameStor->getValues(['year', 'month']);
pushGlobalHistoryLog(["<R>★</>{$admin['year']}{$admin['month']}월: <S>모두들 즐거운 게임 하고 계신가요? ^^ <Y>매너 있는 플레이</> 부탁드리고, <M>지나친 훼접</>은 삼가주세요~</>"], $admin['year'], $admin['month']);
$e_env = $gameStor->getValues(['startyear', 'year', 'month']);
$e_env['currentEventID'] = 0;
Action::build(["ProcessIncome", ResourceType::rice->value])->run($e_env);
}
/** @deprecated */
function processGoldIncome() {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$adminLog = [];
$nationList = $db->query('SELECT name,nation,capital,gold,level,rate_tmp,bill,type from nation');
$cityListByNation = Util::arrayGroupBy($db->query('SELECT * FROM city'), 'nation');
$generalRawListByNation = Util::arrayGroupBy($db->query('SELECT no,name,nation,gold,officer_level,dedication,city FROM general WHERE npc != 5'), 'nation');
//국가별 처리
foreach($nationList as $nation) {
$nationID = $nation['nation'];
$generalRawList = $generalRawListByNation[$nationID];
$income = getGoldIncome($nationID, $nation['level'], $nation['rate_tmp'], $nation['capital'], $nation['type'], $cityListByNation[$nationID]??[]);
$originoutcome = getOutcome(100, $generalRawList);
$outcome= Util::round($nation['bill'] / 100 * $originoutcome);
// 실제 지급량 계산
$nation['gold'] += $income;
// 기본량도 안될경우
if($nation['gold'] < GameConst::$basegold) {
$realoutcome = 0;
// 실지급률
$ratio = 0;
//기본량은 넘지만 요구량이 안될경우
} elseif($nation['gold'] - GameConst::$basegold < $outcome) {
$realoutcome = $nation['gold'] - GameConst::$basegold;
$nation['gold'] = GameConst::$basegold;
// 실지급률
$ratio = $realoutcome / $originoutcome;
} else {
$realoutcome = $outcome;
$nation['gold'] -= $realoutcome;
// 실지급률
$ratio = $realoutcome / $originoutcome;
}
$nation['gold'] = Util::valueFit($nation['gold'], GameConst::$basegold);
$adminLog[] = StringUtil::padStringAlignRight((string)$nation['name'],12," ")
." // 세금 : ".StringUtil::padStringAlignRight((string)$income,6," ")
." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ")
." // 실제 : ".tab2((string)$realoutcome,6," ")
." // 지급률 : ".tab2((string)round($ratio*100,2),5," ")
." % // 결과금 : ".tab2((string)$nation['gold'],6," ");
$incomeText = number_format($income);
$incomeLog = "이번 수입은 금 <C>$incomeText</>입니다.";
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->prev_income_gold = $income;
$db->update('nation', [
'gold'=>$nation['gold']
], 'nation=%i', $nationID);
// 각 장수들에게 지급
foreach ($generalRawList as $rawGeneral) {
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false);
$gold = Util::round(getBill($generalObj->getVar('dedication'))*$ratio);
$generalObj->increaseVar('gold', $gold);
$logger = $generalObj->getLogger();
if($generalObj->getVar('officer_level') > 4){
$logger->pushGeneralActionLog($incomeLog, $logger::PLAIN);
}
$goldText = number_format($gold);
$logger->pushGeneralActionLog("봉급으로 금 <C>$goldText</>을 받았습니다.", $logger::PLAIN);
$generalObj->applyDB($db);
}
}
$logger = new ActionLogger(0, 0, $year, $month);
$logger->pushGlobalHistoryLog('<W><b>【지급】</b></>봄이 되어 봉록에 따라 자금이 지급됩니다.');
$logger->flush();
pushAdminLog($adminLog);
$e_env = $gameStor->getValues(['startyear', 'year', 'month']);
$e_env['currentEventID'] = 0;
Action::build(["ProcessIncome", ResourceType::gold->value])->run($e_env);
}
function popIncrease() {
@@ -304,29 +163,6 @@ function getGoldIncome(int $nationID, int $nationLevel, float $taxRate, int $cap
return $cityIncome;
}
function processWarIncome() {
$db = DB::db();
$cityListByNation = Util::arrayGroupBy($db->query('SELECT * FROM city'), 'nation');
foreach(getAllNationStaticInfo() as $nation){
if($nation['level'] <= 0){
continue;
}
$nationID = $nation['nation'];
$income = getWarGoldIncome($nation['type'], $cityListByNation[$nationID]??[]);
$db->update('nation', [
'gold'=>$db->sqleval('gold + %i', $income)
], 'nation=%i', $nationID);
}
// 10%수입, 20%부상병
$db->update('city', [
'pop'=>$db->sqleval('pop + dead * %d', 0.2),
'dead'=>0
], true);
}
function getWarGoldIncome(string $nationType, array $cityList){
$nationTypeObj = buildNationTypeClass($nationType);
@@ -338,115 +174,14 @@ function getWarGoldIncome(string $nationType, array $cityList){
return $cityIncome;
}
//7월마다 실행
function processFall() {
$db = DB::db();
// 7월엔 무조건 내정 1% 감소
$db->update('city',[
'dead'=>0,
'agri'=>$db->sqleval('agri * 0.99'),
'comm'=>$db->sqleval('comm * 0.99'),
'secu'=>$db->sqleval('secu * 0.99'),
'def'=>$db->sqleval('def * 0.99'),
'wall'=>$db->sqleval('wall * 0.99'),
],true);
//인구 증가
popIncrease();
// > 10000 유지비 3%, > 1000 유지비 1%
// 유지비 1%
$db->update('general', [
'rice'=>$db->sqleval('IF(rice > 10000, rice * 0.97, rice * 0.99)')
], 'rice > 1000');
// > 100000 유지비 5%, > 100000 유지비 3%, > 1000 유지비 1%
$db->update('nation', [
'rice'=>$db->sqleval('IF(rice > 100000, rice * 0.95, IF(rice > 10000, rice * 0.97, rice * 0.99))')
], 'rice > 1000');
}
/** @deprecated */
function processRiceIncome() {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$adminLog = [];
$nationList = $db->query('SELECT name,level,nation,capital,rice,rate_tmp,bill,type from nation');
$cityListByNation = Util::arrayGroupBy($db->query('SELECT * FROM city'), 'nation');
$generalRawListByNation = Util::arrayGroupBy($db->query('SELECT no,name,nation,rice,officer_level,dedication,city FROM general WHERE npc != 5'), 'nation');
//국가별 처리
foreach($nationList as $nation) {
$nationID = $nation['nation'];
$generalRawList = $generalRawListByNation[$nationID];
$income = getRiceIncome($nation['nation'], $nation['level'], $nation['rate_tmp'], $nation['capital'], $nation['type'], $cityListByNation[$nationID]??[]);
$income += getWallIncome($nation['nation'], $nation['level'], $nation['rate_tmp'], $nation['capital'], $nation['type'], $cityListByNation[$nationID]??[]);
$originoutcome = getOutcome(100, $generalRawList);
$outcome= Util::round($nation['bill'] / 100 * $originoutcome);
// 실제 지급량 계산
$nation['rice'] += $income;
// 기본량도 안될경우
if($nation['rice'] < GameConst::$baserice) {
$realoutcome = 0;
// 실지급률
$ratio = 0;
//기본량은 넘지만 요구량이 안될경우
} elseif($nation['rice'] - GameConst::$baserice < $outcome) {
$realoutcome = $nation['rice'] - GameConst::$baserice;
$nation['rice'] = GameConst::$baserice;
// 실지급률
$ratio = $realoutcome / $originoutcome;
} else {
$realoutcome = $outcome;
$nation['rice'] -= $realoutcome;
// 실지급률
$ratio = $realoutcome / $originoutcome;
}
$nation['rice'] = Util::valueFit($nation['rice'], GameConst::$baserice);
$adminLog[] = StringUtil::padStringAlignRight($nation['name'],12," ")
." // 세곡 : ".StringUtil::padStringAlignRight((string)$income,6," ")
." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ")
." // 실제 : ".tab2((string)$realoutcome,6," ")
." // 지급률 : ".tab2((string)round($ratio*100,2),5," ")
." % // 결과곡 : ".tab2((string)$nation['rice'],6," ");
$incomeText = number_format($income);
$incomeLog = "이번 수입은 쌀 <C>$incomeText</>입니다.";
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->prev_income_rice = $income;
$db->update('nation', [
'rice'=>$nation['rice']
], 'nation=%i', $nationID);
// 각 장수들에게 지급
foreach ($generalRawList as $rawGeneral) {
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false);
$rice = Util::round(getBill($generalObj->getVar('dedication'))*$ratio);
$generalObj->increaseVar('rice', $rice);
$logger = $generalObj->getLogger();
if($generalObj->getVar('officer_level') > 4){
$logger->pushGeneralActionLog($incomeLog, $logger::PLAIN);
}
$riceText = number_format($rice);
$logger->pushGeneralActionLog("봉급으로 쌀 <C>$riceText</>을 받았습니다.", $logger::PLAIN);
$generalObj->applyDB($db);
}
}
$logger = new ActionLogger(0, 0, $year, $month);
$logger->pushGlobalHistoryLog('<W><b>【지급】</b></>가을이 되어 봉록에 따라 군량이 지급됩니다.');
$logger->flush();
pushAdminLog($adminLog);
$e_env = $gameStor->getValues(['startyear', 'year', 'month']);
$e_env['currentEventID'] = 0;
Action::build(["ProcessIncome", ResourceType::rice->value])->run($e_env);
}
function getRiceIncome(int $nationID, int $nationLevel, float $taxRate, int $capitalID, string $nationType, ?array $cityList) {
@@ -629,7 +364,14 @@ function disaster(RandUtil $rng) {
$logger->flush();
if (!$isGood) {
$generalListByCity = Util::arrayGroupBy($db->query('SELECT no, name, nation, city, officer_level, injury, leadership, strength, intel, horse, weapon, book, item, crew, crewtype, atmos, train, special, special2 FROM general WHERE city IN %li', Util::squeezeFromArray($targetCityList, 'city')), 'city');
[$queryColumns,,] = General::mergeQueryColumn();
$generalListByCity = Util::arrayGroupBy(
$db->query(
'SELECT %l FROM general WHERE city IN %li',
Util::formatListOfBackticks($queryColumns),
Util::squeezeFromArray($targetCityList, 'city')
),
'city');
//NOTE: 쿼리 1번이지만 복잡하기 vs 쿼리 여러번이지만 조금 더 깔끔하기
foreach ($targetCityList as $city) {
$affectRatio = Util::valueFit($city['secu'] / $city['secu_max'] / 0.8, 0, 1);
@@ -648,7 +390,7 @@ function disaster(RandUtil $rng) {
$generalList = array_map(
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']]??[]
);
+24 -79
View File
@@ -5,17 +5,25 @@ namespace sammo;
use sammo\DTO\BettingInfo;
use sammo\Enums\InheritanceKey;
/**
* @param int $turnTerm 서버 턴 단위
* @return int 토너먼트 초 단위
*/
function calcTournamentTerm(int $turnTerm): int{
return Util::valueFit($turnTerm, 5, 120);
}
function processTournament()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'tnmt_auto', 'tnmt_time', 'last_tournament_betting_id']);
$admin = $gameStor->getValues(['tournament', 'phase', 'tnmt_type', 'tnmt_auto', 'tnmt_time', 'turnterm', 'last_tournament_betting_id']);
$now = new \DateTime();
$offset = $now->getTimestamp() - (new \DateTime($admin['tnmt_time']))->getTimestamp();
//수동일땐 무시
if ($admin['tnmt_auto'] == 0) {
if (!$admin['tnmt_auto']) {
return;
}
@@ -28,18 +36,7 @@ function processTournament()
}
//현시간이 스탬프 지나친경우
$unit = [
1 => 720,
2 => 420,
3 => 180,
4 => 60,
5 => 30,
6 => 15,
7 => 5,
][$admin['tnmt_auto']] ?? null;
if($unit === null){
throw new MustNotBeReachedException();
}
$unit = calcTournamentTerm($admin['turnterm']);
//업데이트 횟수
$iter = intdiv($offset, $unit) + 1;
@@ -123,10 +120,7 @@ function processTournament()
//베팅은 무조건 60페이즈후 진행(최대 1시간)
if ($tnmt == 6) {
$betTerm = $unit * 60;
if ($betTerm > 3600) {
$betTerm = 3600;
}
$betTerm = Util::valueFit($unit * 60, null, 3600);
//처리 초 더한 날짜
$dt = date("Y-m-d H:i:s", strtotime($admin['tnmt_time']) + $unit * $i + $betTerm);
$gameStor->tournament = $tnmt;
@@ -134,20 +128,6 @@ function processTournament()
$gameStor->tnmt_time = $dt;
return;
}
if ($admin['tnmt_auto'] == 1) {
//처리 초 더한 날짜
$dt = date("Y-m-d H:i:s", strtotime($admin['tnmt_time']) + $unit * $i);
$hr = substr($dt, 11, 2);
//지정시간대 넘어가면 중단 20~24시
if ($hr < 20) {
$dt = substr($dt, 0, 11) . "20:00:00";
$gameStor->tournament = $tnmt;
$gameStor->phase = $phase;
$gameStor->tnmt_time = $dt;
return;
}
}
}
$second = $unit * $iter;
@@ -156,35 +136,9 @@ function processTournament()
$gameStor->tnmt_time = (new \DateTimeImmutable($admin['tnmt_time']))->add(new \DateInterval("PT{$second}S"))->format('Y-m-d H:i:s');
}
function getTournamentTerm(): ?int
function getTournamentTermText(int $turnTerm)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$tnmt_auto = $gameStor->tnmt_auto;
if ($tnmt_auto === null) {
$tnmt_auto = $gameStor->tnmt_trig;
}
return [
0 => null,
1 => 12 * 60,
2 => 7 * 60,
3 => 3 * 60,
4 => 1 * 60,
5 => 30,
6 => 15,
7 => 5,
][$tnmt_auto] ?? null;
}
function getTournamentTermText()
{
$term = getTournamentTerm();
if ($term === null) {
return '수동';
}
$term = calcTournamentTerm($turnTerm);
if ($term % 60 === 0) {
$termMin = intdiv($term, 60);
@@ -320,26 +274,18 @@ function printFighting($tournament, $phase)
}
}
function startTournament($auto, $type)
function startTournament($type)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
eraseTnmtFightLogAll();
$unit = [
1 => 60,
2 => 60,
3 => 60,
4 => 60,
5 => 30,
6 => 15,
7 => 5,
][$auto] ?? 60;
$admin = $gameStor->getValues(['year', 'month', 'turnterm']);
$turnTerm = $admin['turnterm'];
$unit = calcTournamentTerm($turnTerm);
$admin = $gameStor->getValues(['year', 'month']);
$gameStor->tnmt_auto = $auto;
$gameStor->tnmt_auto = true;
$gameStor->tnmt_time = (new \DateTimeImmutable())->add(new \DateInterval("PT{$unit}M"))->format('Y-m-d H:i:s');
$gameStor->tournament = 1;
$gameStor->tnmt_type = $type;
@@ -392,7 +338,7 @@ function getDummyBettingInfo(string $tnmt_type): BettingInfo
);
}
function startBetting($type, $unit)
function startBetting($type)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -431,7 +377,6 @@ function startBetting($type, $unit)
aux: $general
);
}
$candidateCnt = count($candidates);
Betting::openBetting(new BettingInfo(
id: $bettingID,
@@ -937,7 +882,7 @@ function setGift($tnmt_type, $tnmt, $phase)
//포상 장수 이름, 금액
$resultHelper[$generalID]['reward'] += $cost;
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>4강 진출</span>";
General::createGeneralObjFromDB($generalID)->increaseInheritancePoint(InheritanceKey::tournament, 10);
General::createObjFromDB($generalID)->increaseInheritancePoint(InheritanceKey::tournament, 10);
}
//결승자 명성 돈
$cost = $admin['develcost'] * 6;
@@ -982,7 +927,7 @@ function setGift($tnmt_type, $tnmt, $phase)
}
//자동진행 끝
$gameStor->tnmt_auto = 0;
$gameStor->tnmt_auto = false;
//장수열전 기록
/** @var ActionLogger */
@@ -1001,7 +946,7 @@ function setGift($tnmt_type, $tnmt, $phase)
$winnerLogger->pushGlobalHistoryLog("<B><b>【대회】</b></><C>{$tp}</> 대회에서 <Y>{$winner['name']}</>{$josaYiWinner} <C>우승</>, <Y>{$runnerUp['name']}</>{$josaYiRunnerUp} <C>준우승</>을 차지하여 천하에 이름을 떨칩니다!", ActionLogger::EVENT_YEAR_MONTH);
$winnerLogger->pushGlobalHistoryLog("<B><b>【대회】</b></><C>{$tp}</> 대회의 <S>우승자</>에게는 <C>{$winnerRewardText}</>, <S>준우승자</>에겐 <C>{$runnerUpRewardText}</>의 <S>상금</>과 약간의 <S>명성</>이 주어집니다!", ActionLogger::EVENT_YEAR_MONTH);
$generalObjList = General::createGeneralObjListFromDB(array_keys($resultHelper));
$generalObjList = General::createObjListFromDB(array_keys($resultHelper));
foreach ($resultHelper as $generalID => $general) {
$rewardText = number_format($general['reward']);
@@ -1041,7 +986,7 @@ function setRefund()
}
//자동진행 끝
$gameStor->tnmt_auto = 0;
$gameStor->tnmt_auto = false;
}
//10차이 1.1, 50 차이 1.17, 100차이 1.2
+21 -429
View File
@@ -2,452 +2,44 @@
namespace sammo;
use sammo\DTO\VoteInfo;
include "lib.php";
include "func.php";
Session::requireLogin()->loginGame()->setReadOnly();
$session = Session::requireLogin()->loginGame()->setReadOnly();
$userID = Session::getUserID();
$mapName = GameConst::$mapName;
increaseRefresh("메인", 1);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if (!$userID) {
header('Location:..');
die();
}
//턴 실행.
TurnExecutionHelper::executeAllCommand();
if (!$session->isGameLoggedIn()) {
header('Location:..');
die();
}
$me = $db->queryFirstRow(
'SELECT no,con,turntime,newmsg,newvote,`officer_level` from general where owner = %i',
$userID
);
//그새 사망이면
if ($me === null) {
$session->logoutGame();
header('Location: ../');
die();
}
$gameStor->cacheAll(true);
if ($me['newmsg'] == 1 || $me['newvote'] == 1) {
$db->update('general', [
'newmsg' => 0,
'newvote' => 0
], 'owner=%i', $userID);
}
$plock = boolval($db->queryFirstField('SELECT plock FROM plock WHERE `type`="GAME" LIMIT 1'));
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
$generalObj = General::createGeneralObjFromDB($me['no']);
$generalObj->setRawCity($db->queryFirstRow('SELECT * FROM city WHERE city = %i', $generalObj->getCityID()));
$scenario = $gameStor->scenario_text;
$nationID = $generalObj->getNationID();
if ($nationID) {
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->cacheAll();
}
if ($gameStor->extended_general == 0) {
$extend = "표준";
} else {
$extend = "확장";
}
if ($gameStor->fiction == 0) {
$fiction = "사실";
} else {
$fiction = "가상";
}
if ($gameStor->npcmode == 0) {
$npcmode = "불가능";
} else if ($gameStor->npcmode == 1) {
$npcmode = "가능";
} else {
$npcmode = "선택 생성";
}
$color = "cyan";
$serverName = UniqueConst::$serverName;
$serverCnt = $gameStor->server_cnt;
$auctionCount = $db->queryFirstField('SELECT count(*) FROM ng_auction WHERE finished = 0');
$isTournamentActive = $gameStor->tournament > 0;
$isTournamentApplicationOpen = $gameStor->tournament == 1;
$isBettingActive = $gameStor->tournament == 6;
$myNationStatic = getNationStaticInfo($generalObj->getNationID());
$nationColorType = substr($myNationStatic['color'] ?? '#000000', 1);
$autorunUser = ($gameStor->autorun_user) ?? [];
$otherTextInfo = [];
if ($gameStor->join_mode == 'onlyRandom') {
$otherTextInfo[] = '랜덤 임관 전용';
}
if ($autorunUser['limit_minutes'] ?? false) {
$otherTextInfo[] = getAutorunInfo($autorunUser);
}
if (!$otherTextInfo) {
$otherTextInfo = '표준';
} else {
$otherTextInfo = join(', ', $otherTextInfo);
}
$lastVoteID = $gameStor->lastVote;
$lastVote = null;
if ($lastVoteID) {
$voteStor = KVStorage::getStorage($db, 'vote');
$lastVote = VoteInfo::fromArray($voteStor->getValue("vote_{$lastVoteID}"));
if ($lastVote->endDate && $lastVote->endDate < TimeUtil::now()) {
$lastVote = null;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title><?= $serverName ?>: 메인</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=500" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('d_shared/base_map.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('vue', 'v_main', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/map.css') ?>
<title><?= UniqueConst::$serverName ?>: 메인</title>
<?= WebUtil::printStaticValues([
//deprecated, staticValues를 이용할 것
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'staticValues' => [
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'commandList' => getCommandTable($generalObj),
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'mapName' => GameConst::$mapName,
'unitSet' => GameConst::$unitSet,
'serverName' => UniqueConst::$serverName,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'mapName' => GameConst::$mapName,
'unitSet' => GameConst::$unitSet,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'serverNow' => TimeUtil::now(false),
]
]) ?>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
], false) ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS("js/map/theme_{$mapName}.js") ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('vue', 'v_front', true) ?>
</head>
<body class="img_back sam-color-<?= $nationColorType ?>">
<div id="container" class="bg0">
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></button></div>
</div>
<div class="tb_layout row gx-0">
<div id="server_title" class="row py-2 center">
<h3>삼국지 모의전투 HiDCHe <?= $serverName . $serverCnt ?>기 <span class="avoid-wrap">(<font color=cyan><?= $scenario ?></font>)</span></h3>
</div>
<div class="row center gx-0">
<div class="s-border-t col py-2 col-8 col-md-4" style="color:<?= $color ?>;">
<?= $scenario ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC 수, 상성 : <?= $extend ?>,<?= $fiction ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC선택 : <?= $npcmode ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
토너먼트 : <?= getTournamentTermText() ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
기타 설정: <?= $otherTextInfo ?>
</div>
<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-4 col-md-2">전체 접속자 수 : <?= $gameStor->online_user_cnt ?> 명</div>
<div class="s-border-t col py-2 col-4 col-md-2">턴당 갱신횟수 : <?= $gameStor->conlimit ?>회</div>
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(3) ?></div>
<div class="s-border-t py-2 col col-6 col-md-4">
<?php if ($isTournamentActive) : ?>
↑<span style='color:cyan'><?= (['전력전', '통솔전', '일기토', '설전',])[$gameStor->tnmt_type] ?? '' ?> <?= getTournament($gameStor->tournament) ?> <?= getTournamentTime() ?></span>↑
<?php else : ?>
<span style='color:magenta'>현재 토너먼트 경기 없음</span>
<?php endif; ?>
</div>
<div class="s-border-t py-2 col col-6 col-md-2">
<div style="display:inline-block;"><?= $plock ? ("<span style='color:magenta;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") : ("<span style='color:cyan;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") ?></div>
</div>
<div class="s-border-t py-2 col col-6 col-md-2">
<?php if ($auctionCount > 0) : ?>
<span style='color:cyan'><?= $auctionCount ?>건</span> 거래 진행중
<?php else : ?>
<span style='color:magenta'>진행중 거래 없음</span>
<?php endif; ?>
</div>
<div class="s-border-t py-2 col col-6 col-md-4 vote-cell">
<?php
?>
<?php if ($lastVote === null) : ?>
<span style='color:magenta'>진행중 설문 없음</span>
<?php else : ?>
<span style='color:cyan'>설문 진행중</span> : <span><?= $lastVote->title ?></span>
<?php endif; ?>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">접속중인 국가: <?= $gameStor->online_nation ?></div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">운영자 메세지 : <span style='color:yellow;'><?= $gameStor->msg ?></span></div>
</div>
<div class="row gx-0">
<div class="col s-border-t py-2" id="nation-msg-position">
<div class="px-2">【 국가방침 】</div>
<div id='nation-msg-box'>
<div id='nation-msg'><?= nationMsg($generalObj) ?></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">
【 접속자 】<?= onlinegen($generalObj) ?>
</div>
</div>
<?php if ($session->userGrade >= 5) : ?>
<div class="row">
<div class="col">
<a href='_admin1.php' target='_blank'><button type='button'>게임관리</button></a>
<a href='_admin2.php' target='_blank'><button type='button'>회원관리</button></a>
<a href='_admin4.php' target='_blank'><button type='button'>멀티관리</button></a>
<a href='_admin5.php' target='_blank'><button type='button'>일제정보</button></a>
<a href='_admin7.php' target='_blank'><button type='button'>로그정보</button></a>
<a href='_admin8.php' target='_blank'><button type='button'>외교정보</button></a>
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php elseif ($session->userGrade == 4) : ?>
<div class="row">
<div class="col">
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php endif; ?>
<div id="map_view" class="gx-0">
<div id="mapZone" class="view-item"><?= getMapHtml() ?></div>
<div class="view-item" id="reservedCommandZone">
<div id="reservedCommandList"></div>
<div id="actionMiniPlate" class="gx-0 row">
<div class="col">
<div class="gx-1 row">
<div class="col-8 d-grid"><button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button></div>
<div class="col-4 d-grid"><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></div>
</div>
</div>
</div>
</div>
<div id="cityInfo" class="view-item" style="border:none;text-align:center;"><?= cityInfo($generalObj) ?></div>
<div id="nation-position"><?php myNationInfo($generalObj); ?></div>
<div id="general-position"><?php generalInfo($generalObj); ?></div>
<div id="generalCommandButton" class="row gx-0">
<div class="buttonPlate bg2">
<?= commandButton([
'splitBtnBegin' => '<div class="btn-group">',
'splitBtnEnd' => '</div>',
'splitZoneSign' => '<button type="button" class="btn btn-sammo-nation dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"><span class="visually-hidden">Toggle Dropdown</span></button>',
'splitZoneBegin' => '<ul class="dropdown-menu dropdown-menu-end">',
'splitZoneEnd' => '</ul>',
'splitSubBtnBegin' => '<li>',
'splitSubBtnEnd' => '</li>',
'btnClass' => 'btn btn-sammo-nation',
'btnSplitClass' => 'dropdown-item',
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive
])
?></div>
</div>
</div>
</div>
<div id="actionMiniPlateSub" class="gx-0 row">
<div class="col">
<div class="gx-1 row">
<div class="col-3 d-grid"><button type='button' class="btn btn-dark" onclick="scrollHardTo('reservedCommandList')">명령으로</button></div>
<div class="col-5 d-grid"><button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button></div>
<div class="col-4 d-grid"><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col-md-6" id="general_public_record-position">
<div class="bg1 center s-border-tb"><b>장수 동향</b></div>
<div id="general_public_record" style="text-align:left;"><?= formatHistoryToHTML(getGlobalActionLogRecent(15)) ?></div>
</div>
<div class="col-md-6" id="general_log-position">
<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>
<div class="col-12" id="world_history-position">
<div class="bg1 center s-border-tb"><b>중원 정세</b></div>
<div id="world_history" colspan=2 style="text-align:left;"><?= formatHistoryToHTML(getGlobalHistoryLogRecent(15)) ?></div>
</div>
</div>
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></div>
<div id="message_board" class="row gx-0">
<div class="message_input_form bg0 gx-0 row">
<div id="mailbox_list-col" class="col-6 col-md-2 d-grid">
<select id="mailbox_list" size="1" class="form-control bg-dark text-white">
</select>
</div>
<div id="msg_input-col" class="col-12 col-md-8 d-grid">
<input type="text" id="msg_input" maxlength="99" class="form-control">
</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>
<div class="col-md-6 board_side bg0"><a id="public_talk_position"></a>
<div class="board_header bg0">전체 메시지(최고99자)</div>
<section class="public_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="public">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0"><a id="national_talk_position"></a>
<div class="board_header bg0">국가 메시지(최고99자)</div>
<section class="national_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="national">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0"><a id="private_talk_position"></a>
<div class="board_header bg0">개인 메시지(최고99자)</div>
<section class="private_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="private">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0"><a id="diplomacy_talk_position"></a>
<div class="board_header bg0">외교 메시지(최고99자)</div>
<section class="diplomacy_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="diplomacy">이전 메시지 불러오기</button></div>
</section>
</div>
</div>
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></div><?= banner() ?>
</div>
</div>
<?php
if ($con == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!");
}
if ($me['newmsg'] == 1) {
MessageBox("새로운 서신이 도착했습니다!");
}
if ($me['newvote'] == 1) {
$develcost = $gameStor->develcost * 5;
MessageBox("설문조사에 참여하시면 금{$develcost}과 유니크템을 드립니다! (우측 상단 설문조사 메뉴)");
}
?>
</div>
<nav class="navbar navbar-expand fixed-bottom navbar-dark bg-dark d-sm-block d-md-none p-0" id="navbar500">
<div class="container-fluid px-0">
<div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mx-auto">
<li class="nav-item dropup">
<div class="dropdown-toggle text-white btn btn-sammo-base2" id="navbarGlobal" role="button" data-bs-toggle="dropdown" aria-expanded="false">
외부 메뉴
</div>
<ul class="dropdown-menu dropdown-menu-start" aria-labelledby="navbarGlobal" id="navbarGlobalItems">
<?= allButton($gameStor->npcmode == 1, ['btnBegin' => '<li>', 'btnEnd' => '</li>', 'btnClass' => 'dropdown-item']) ?>
</ul>
</li>
<li class="nav-item dropup">
<div class="dropdown-toggle btn btn-sammo-nation" id="navbarNation" role="button" data-bs-toggle="dropdown" aria-expanded="false">
국가 메뉴
</div>
<ul class="dropdown-menu" aria-labelledby="navbarNation" id="navbarNationItems">
<?= commandButton([
'btnBegin' => '<li>',
'btnEnd' => '</li>',
'splitMainBegin' => '<div class="d-none">',
'splitMainEnd' => '</div>',
'splitSubBtnBegin' => '<li>',
'splitSubBtnEnd' => '</li>',
'btnClass' => 'dropdown-item',
'btnSplitClass' => 'dropdown-item',
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive
]) ?>
</ul>
</li>
<li class="nav-item dropup">
<div class="dropdown-toggle text-white btn btn-dark" id="navbarQuick" role="button" data-bs-toggle="dropdown" aria-expanded="false">
빠른 이동
</div>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown" id="navbarQuickItems">
<li><a class="dropdown-item disabled">국가 정보</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('nation-msg-position')" class="dropdown-item">방침</button></li>
<li><button type="button" onclick="scrollHardTo('reservedCommandList')" class="dropdown-item">명령</button></li>
<li><button type="button" onclick="scrollHardTo('nation-position')" class="dropdown-item">국가</button></li>
<li><button type="button" onclick="scrollHardTo('general-position')" class="dropdown-item">장수</button></li>
<li><button type="button" onclick="scrollHardTo('cityInfo')" class="dropdown-item">도시</button></li>
<li><a class="dropdown-item disabled">동향 정보</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('mapZone')" class="dropdown-item">지도</button></li>
<li><button type="button" onclick="scrollHardTo('general_public_record-position')" class="dropdown-item">동향</button></li>
<li><button type="button" onclick="scrollHardTo('general_log-position')" class="dropdown-item">개인</button></li>
<li><button type="button" onclick="scrollHardTo('world_history-position')" class="dropdown-item">정세</button></li>
<li><span>&nbsp;</span></li>
<li><a class="dropdown-item disabled">메시지</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('public_talk_position')" class="dropdown-item">전체</button></li>
<li><button type="button" onclick="scrollHardTo('national_talk_position')" class="dropdown-item">국가</button></li>
<li><button type="button" onclick="scrollHardTo('private_talk_position')" class="dropdown-item">개인</button></li>
<li><button type="button" onclick="scrollHardTo('diplomacy_talk_position')" class="dropdown-item">외교</button></li>
<li><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></li>
</ul>
</li>
<li class="nav-item">
<a class="refreshPage btn btn-sammo-base2 text-white" role="button">갱신</a>
</li>
</ul>
</div>
</div>
</nav>
<body>
<div id="app"></div>
</body>
</html>
+18 -21
View File
@@ -28,17 +28,19 @@ if ($session->userGrade < 5 && !$allowReset) {
<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=device-width, initial-scale=1" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printCSS('css/install.css') ?>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common', 'install']) ?>
</head>
<body>
<div class="container">
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 리셋</h1>
<div class="row justify-content-md-center">
<h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 리셋</h1>
<div class="row justify-content-lg-center">
<div class="col col-lg-8">
<div class="card" id="game_form_card">
@@ -92,8 +94,8 @@ if ($session->userGrade < 5 && !$allowReset) {
<label for="fiction" class="col-sm-3 col-form-label">NPC 상성</label>
<div class="col-sm-9">
<div id="fiction" class="btn-group btn-group-toggle" data-bs-toggle="buttons">
<input type="radio" id="fiction_0" class="btn-check" name="fiction" value="0" checked><label for="fiction_0" class="btn btn-secondary"> 연의 </label>
<input type="radio" id="fiction_1" class="btn-check" name="fiction" value="1"><label for="fiction_1" class="btn btn-secondary"> 가상 </label>
<input type="radio" id="fiction_0" class="btn-check" name="fiction" value="0"><label for="fiction_0" class="btn btn-secondary"> 연의 </label>
<input type="radio" id="fiction_1" class="btn-check" name="fiction" value="1" checked><label for="fiction_1" class="btn btn-secondary"> 가상 </label>
</div>
</div>
</div>
@@ -113,6 +115,7 @@ if ($session->userGrade < 5 && !$allowReset) {
<div class="col-sm-9">
<div id="block_general_create" class="btn-group btn-group-toggle" data-bs-toggle="buttons">
<input type="radio" class="btn-check" id="block_general_create_0" name="block_general_create" value="0" checked><label for="block_general_create_0" class="btn btn-secondary">가능</label>
<input type="radio" class="btn-check" id="block_general_create_2" name="block_general_create" value="2"><label for="block_general_create_2" class="btn btn-secondary">장수명무작위</label>
<input type="radio" class="btn-check" id="block_general_create_1" name="block_general_create" value="1"><label for="block_general_create_1" class="btn btn-secondary">불가</label>
</div>
</div>
@@ -134,13 +137,13 @@ if ($session->userGrade < 5 && !$allowReset) {
<div class="col-sm-9">
<div class="input-group">
<div class="btn-group btn-group-toggle" data-bs-toggle="buttons">
<input type="checkbox" id="autorun_develop" class="autorun_user_chk btn-check" data-key="develop" name="autorun_user[]" value="develop"><label class="btn btn-secondary" for="autorun_develop">내정</label>
<input type="checkbox" id="autorun_warp" class="autorun_user_chk btn-check" data-key="warp" name="autorun_user[]" value="warp"><label class="btn btn-secondary" for="autorun_warp">순간이동</label>
<input type="checkbox" id="autorun_recruit" class="autorun_user_chk btn-check" data-key="recruit" name="autorun_user[]" value="recruit"><label class="btn btn-secondary" for="autorun_recruit">징병</label>
<input type="checkbox" id="autorun_recruit_high" class="autorun_user_chk btn-check" data-key="recruit_high" name="autorun_user[]" value="recruit_high"><label class="btn btn-secondary" for="autorun_recruit_high">모병</label>
<input type="checkbox" id="autorun_train" class="autorun_user_chk btn-check" data-key="train" name="autorun_user[]" value="train"><label class="btn btn-secondary" for="autorun_train">훈사</label>
<input type="checkbox" id="autorun_battle" class="autorun_user_chk btn-check" data-key="battle" name="autorun_user[]" value="battle"><label class="btn btn-secondary" for="autorun_battle">출병</label>
<input type="checkbox" id="autorun_chief" class="autorun_user_chk btn-check" data-key="chief" name="autorun_user[]" value="chief"><label class="btn btn-secondary" for="autorun_chief">기본 사령턴</label>
<input type="checkbox" id="autorun_develop" class="autorun_user_chk btn-check" data-key="develop" name="autorun_user[]" value="develop" checked><label class="btn btn-secondary" for="autorun_develop">내정</label>
<input type="checkbox" id="autorun_warp" class="autorun_user_chk btn-check" data-key="warp" name="autorun_user[]" value="warp" checked><label class="btn btn-secondary" for="autorun_warp">순간이동</label>
<input type="checkbox" id="autorun_recruit" class="autorun_user_chk btn-check" data-key="recruit" name="autorun_user[]" value="recruit" checked><label class="btn btn-secondary" for="autorun_recruit">징병</label>
<input type="checkbox" id="autorun_recruit_high" class="autorun_user_chk btn-check" data-key="recruit_high" name="autorun_user[]" value="recruit_high" checked><label class="btn btn-secondary" for="autorun_recruit_high">모병</label>
<input type="checkbox" id="autorun_train" class="autorun_user_chk btn-check" data-key="train" name="autorun_user[]" value="train" checked><label class="btn btn-secondary" for="autorun_train">훈사</label>
<input type="checkbox" id="autorun_battle" class="autorun_user_chk btn-check" data-key="battle" name="autorun_user[]" value="battle" checked><label class="btn btn-secondary" for="autorun_battle">출병</label>
<input type="checkbox" id="autorun_chief" class="autorun_user_chk btn-check" data-key="chief" name="autorun_user[]" value="chief" checked><label class="btn btn-secondary" for="autorun_chief">기본 사령턴</label>
</div>
</div>
</div>
@@ -162,7 +165,7 @@ if ($session->userGrade < 5 && !$allowReset) {
<option value="480">8시간</option>
<option value="600">10시간</option>
<option value="720">12시간</option>
<option value="1440">24시간</option>
<option value="1440" selected>24시간</option>
<option value="2160">36시간</option>
<option value="2880">48시간</option>
<option value="3600">60시간</option>
@@ -194,17 +197,11 @@ if ($session->userGrade < 5 && !$allowReset) {
</div>
<div class="form-group row">
<label for="tournament_trig" class="col-sm-3 col-form-label"><span class="text-nowrap">토너먼트 자동 시작</span> <span class="text-nowrap">경기 단위</span></label>
<label for="tournament_trig" class="col-sm-3 col-form-label"><span class="text-nowrap">토너먼트 자동 시작</span></label>
<div class="col-sm-9" id="tournament_trig">
<div id="tournament_trig" class="btn-group-toggle btn-group flex-wrap" data-bs-toggle="buttons">
<input type="radio" class="btn-check" id="tournament_trig_0" name="tournament_trig" value="0"><label for="tournament_trig_0" class="btn btn-secondary w-25">안함</label>
<input type="radio" class="btn-check" id="tournament_trig_1" name="tournament_trig" value="1"><label for="tournament_trig_1" class="btn btn-secondary w-25">12분(총 5일)</label>
<input type="radio" class="btn-check" id="tournament_trig_2" name="tournament_trig" value="2"><label for="tournament_trig_2" class="btn btn-secondary w-25">7분(총 10시간)</label>
<input type="radio" class="btn-check" id="tournament_trig_3" name="tournament_trig" value="3"><label for="tournament_trig_3" class="btn btn-secondary w-25">3분(총 4시간)</label>
<input type="radio" class="btn-check" id="tournament_trig_4" name="tournament_trig" value="4" checked><label for="tournament_trig_4" class="btn btn-secondary w-25">1분(총 82분)</label>
<input type="radio" class="btn-check" id="tournament_trig_5" name="tournament_trig" value="5"><label for="tournament_trig_5" class="btn btn-secondary w-25">30초(총 41분)</label>
<input type="radio" class="btn-check" id="tournament_trig_6" name="tournament_trig" value="6"><label for="tournament_trig_6" class="btn btn-secondary w-25">15초(총 21분)</label>
<input type="radio" class="btn-check" id="tournament_trig_7" name="tournament_trig" value="7"><label for="tournament_trig_7" class="btn btn-secondary w-25">5초(총 7분)</label>
<input type="radio" class="btn-check" id="tournament_trig_0" name="tournament_trig" value="0"><label for="tournament_trig_0" class="btn btn-secondary w-25">수동</label>
<input type="radio" class="btn-check" id="tournament_trig_1" name="tournament_trig" checked value="1"><label for="tournament_trig_1" class="btn btn-secondary w-25">자동</label>
</div>
</div>
</div>
+3 -2
View File
@@ -21,6 +21,7 @@ if ($session->userGrade == 5) {
<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=device-width, initial-scale=1" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
@@ -31,8 +32,8 @@ if ($session->userGrade == 5) {
<body>
<div class="container" style="min-width:720px;">
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 리셋</h1>
<div class="row justify-content-md-center">
<h1 class="row justify-content-lg-center">삼국지 모의전투 HiDCHe 리셋</h1>
<div class="row justify-content-lg-center">
<div class="col col-lg-8">
<div class="card" id="db_form_card">
+2 -2
View File
@@ -56,7 +56,7 @@ else if(
$status = 'closed';
}
else if(
$isUnited > 0 &&
$isUnited > 0 &&
$now->getTimestamp() - $lastTurn->getTimestamp() > ($reservedDate->getTimestamp() - $now->getTimestamp()) * 2
){
//천통 & 비정지 상태 & 2/3 넘음
@@ -88,7 +88,7 @@ $result = ResetHelper::buildScenario(
$options['block_general_create'],
$options['npcmode'],
$options['show_img_level'],
$options['tournament_trig'],
!!$options['tournament_trig'],
$options['join_mode'],
$options['starttime'],
$options['autorun_user']?:null
+7 -4
View File
@@ -17,10 +17,13 @@ $text = Util::getPost('text');
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']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한입니다.'
@@ -50,7 +53,7 @@ if($permission < 0){
'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.'
]);
}
else if ($isSecretBoard && $permission < 2) {
Json::die([
+7 -4
View File
@@ -16,10 +16,13 @@ $text = Util::getPost('text');
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']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한입니다.'
@@ -58,7 +61,7 @@ if($permission < 0){
'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.'
]);
}
else if ($isSecretBoard && $permission < 2) {
Json::die([
+7 -5
View File
@@ -16,11 +16,14 @@ $isSecretBoard = Util::getPost('isSecret', 'bool', false);
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']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한입니다.'
@@ -33,7 +36,7 @@ if($permission < 0){
'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.'
]);
}
else if ($isSecretBoard && $permission < 2) {
Json::die([
@@ -72,4 +75,3 @@ Json::die([
'articles'=>$articles,
'reason'=>'success'
]);
-61
View File
@@ -1,61 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$availableDieImmediately = false;
//로그인 검사
$session = Session::requireGameLogin();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$general = $db->queryFirstRow('SELECT no,name,owner_name,npc,lastrefresh FROM general WHERE owner=%i AND npc = 0', $userID);
if(!$general){
Json::die([
'result'=>false,
'reason'=>'장수가 없습니다.'
]);
}
increaseRefresh("장수 삭제", 1);
$gameStor->cacheValues(['turnterm', 'opentime', 'turntime', 'year', 'month']);
if($gameStor->turntime > $gameStor->opentime){
Json::die([
'result'=>false,
'reason'=>'이미 서버가 시작되었습니다.'
]);
}
$targetTime = addTurn($general['lastrefresh'], $gameStor->turnterm, 2);
if($targetTime > TimeUtil::now()){
$targetTimeShort = substr($targetTime, 0, 19);
Json::die([
'result'=>false,
'reason'=>"아직 삭제할 수 없습니다. {$targetTimeShort} 부터 가능합니다."
]);
}
$generalObj = General::createGeneralObjFromDB($general['no']);
if($generalObj instanceof DummyGeneral){
trigger_error("올바르지 않은 삭제 프로세스 $userID", E_USER_WARNING);
}
$generalName = $generalObj->getName();
$josaYi = JosaUtil::pick($generalName, '이');
$generalObj->kill($db, true, "<Y>{$generalName}</>{$josaYi} 이 홀연히 모습을 <R>감추었습니다</>");
$session->logoutGame();
Json::die([
'result'=>true,
'reason'=>'success'
]);
+11 -6
View File
@@ -1,6 +1,8 @@
<?php
namespace sammo;
use sammo\Enums\MessageType;
include "lib.php";
include "func.php";
@@ -15,10 +17,13 @@ $letterNo = Util::getPost('letterNo', 'int');
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']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한입니다.'
@@ -100,7 +105,7 @@ if(in_array($stateOpt, ['try_destroy_src', 'try_destroy_dest'])){
'reason'=>'파기'
];
}
$msgText = "외교 서신 #{$letterNo} 파기했습니다.";
$msgText = "외교 서신(#{$letterNo})을 파기했습니다.";
$lastState = 'cancelled';
}
else{
@@ -114,12 +119,12 @@ else{
'aux'=>Json::encode($aux)
], 'no=%i', $letterNo);
$msgText = "외교 서신 #{$letterNo} 파기 요청합니다.";
$msgText = "외교 서신(#{$letterNo})을 파기 요청합니다.";
$lastState = 'activated';
}
$msg = new Message(
Message::MSGTYPE_DIPLOMACY,
MessageType::diplomacy,
$src,
$dest,
$msgText,
+7 -5
View File
@@ -16,11 +16,14 @@ $isSecretBoard = Util::getPost('isSecret', 'bool', false);
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']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한입니다.'
@@ -33,7 +36,7 @@ if($permission < 0){
'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.'
]);
}
$letters = [];
@@ -83,4 +86,3 @@ Json::die([
'myNationID'=>$me['nation'],
'reason'=>'success'
]);
+12 -7
View File
@@ -1,6 +1,8 @@
<?php
namespace sammo;
use sammo\Enums\MessageType;
include "lib.php";
include "func.php";
@@ -20,10 +22,13 @@ $reason = Util::getPost('reason', 'string', '');
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']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한입니다.'
@@ -85,7 +90,7 @@ if($isAgree){
], 'no=%i', $prevLetterNo);
$prevLetterNo = $db->queryFirstField('SELECT prev_no FROM ng_diplomacy WHERE state != \'cancelled\' AND no = %i', $prevLetterNo);
}
$msgText = "외교 서신 #{$letterNo} 승인되었습니다.";
$msgText = "외교 서신( #{$letterNo})이 승인되었습니다.";
}
else{
$aux['reason'] = [
@@ -97,14 +102,14 @@ else{
'state'=>'cancelled',
'aux'=>Json::encode($aux)
], 'no=%i', $letterNo);
$msgText = "외교 서신 #{$letterNo} 거부되었습니다.";
$msgText = "외교 서신(#{$letterNo})이 거부되었습니다.";
if($reason){
$msgText .= ' 이유 : '.$reason;
}
}
$msg = new Message(
Message::MSGTYPE_DIPLOMACY,
MessageType::diplomacy,
$src,
$dest,
$msgText,
@@ -115,7 +120,7 @@ $msg = new Message(
$msgID = $msg->send();
$msg = new Message(
Message::MSGTYPE_NATIONAL,
MessageType::national,
$src,
$dest,
$msgText,
+10 -5
View File
@@ -1,6 +1,8 @@
<?php
namespace sammo;
use sammo\Enums\MessageType;
include "lib.php";
include "func.php";
@@ -15,10 +17,13 @@ $letterNo = Util::getPost('letterNo', 'int');
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']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한입니다.'
@@ -70,10 +75,10 @@ $db->update('ng_diplomacy', [
'state'=>'cancelled',
'aux'=>Json::encode($aux)
], 'no=%i', $letterNo);
$msgText = "외교 서신 #{$letterNo} 회수되었습니다.";
$msgText = "외교 서신(#{$letterNo})이 회수되었습니다.";
$msg = new Message(
Message::MSGTYPE_DIPLOMACY,
MessageType::diplomacy,
$src,
$dest,
$msgText,
+9 -4
View File
@@ -1,6 +1,8 @@
<?php
namespace sammo;
use sammo\Enums\MessageType;
include "lib.php";
include "func.php";
@@ -22,10 +24,13 @@ if($prevNo < 1){
$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']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한입니다.'
@@ -176,7 +181,7 @@ else{
$msg = new Message(
Message::MSGTYPE_DIPLOMACY,
MessageType::diplomacy,
$src,
$dest,
$msgText,
+7 -4
View File
@@ -33,12 +33,15 @@ if($generalID <= 0 || $reqTo <= 0){
$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'];
$con = checkLimit($me['con']);
if ($con >= 2) {
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한입니다.'
@@ -61,7 +64,7 @@ if($generalID !== $targetID){
'reason'=>'권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.'
]);
}
if($testGeneralNationID !== $nationID){
Json::die([
'result'=>false,
+24 -16
View File
@@ -109,9 +109,9 @@ $scenario = (int)$_POST['scenario'];
$fiction = (int)$_POST['fiction'];
$extend = (int)$_POST['extend'];
$npcmode = (int)$_POST['npcmode'];
$block_general_create = (bool)$_POST['block_general_create'];
$block_general_create = (int)$_POST['block_general_create'];
$show_img_level = (int)$_POST['show_img_level'];
$tournament_trig = (int)$_POST['tournament_trig'];
$tournament_trig = !!(int)$_POST['tournament_trig'];
$join_mode = $_POST['join_mode'];
$autorun_user_minutes = (int)$_POST['autorun_user_minutes'];
$autorun_user_options = [];
@@ -199,17 +199,25 @@ if($reserve_open){
]);
}
Json::die(ResetHelper::buildScenario(
$turnterm,
$sync,
$scenario,
$fiction,
$extend,
$block_general_create,
$npcmode,
$show_img_level,
$tournament_trig,
$join_mode,
TimeUtil::now(),
$autorun_user
));
try{
Json::die(ResetHelper::buildScenario(
$turnterm,
$sync,
$scenario,
$fiction,
$extend,
$block_general_create,
$npcmode,
$show_img_level,
!!$tournament_trig,
$join_mode,
TimeUtil::now(),
$autorun_user
));
}
catch(\Exception $e){
Json::die([
'result'=>false,
'reason'=>$e->getMessage()
]);
}
-19
View File
@@ -1,19 +0,0 @@
<?php
namespace sammo;
include('lib.php');
include('func.php');
$session = Session::requireGameLogin([])->setReadOnly();
if(!Session::getInstance()->generalID){
Json::die([
"nation"=>[]
]);
}
//NOTE: 모든 국가, 모든 장수에 대해서 같은 결과라면 캐싱 가능하지 않을까?
Json::die([
"nation"=>getMailboxList()
]);
-63
View File
@@ -1,63 +0,0 @@
<?php
namespace sammo;
include 'lib.php';
include 'func.php';
WebUtil::requireAJAX();
//{msgID: 1206, response: true}
$session = Session::requireGameLogin([])->setReadOnly();
$generalID = Session::getInstance()->generalID;
if (!$generalID) {
Json::die([
'result'=>false,
'reason'=>'로그인하지 않음'
]);
}
$jsonPost = Json::decode(Util::getPost('data', 'string', '{}'));
$msgID = Util::toInt($jsonPost['msgID']??null);
$msgResponse = $jsonPost['response']??null;
if ($msgID === null || !is_bool($msgResponse)) {
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 인자'
]);
}
$general = DB::db()->queryFirstRow('SELECT `no`, `name`, `nation`, `officer_level`, `npc`, `gold`, `rice`, `troop`, `aux` from `general` where `no` = %i', $generalID);
if(!$general){
Json::die([
'result'=>false,
'reason'=>'존재하지 않는 장수'
]);
}
$msg = Message::getMessageByID($msgID);
if($msg === null){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 메시지'
]);
}
$reason = 'success';
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
$gameStor->cacheAll();
if($msgResponse){
$result = $msg->agreeMessage($general['no'], $reason);
}
else{
$result = $msg->declineMessage($general['no'], $reason);
}
Json::die([
'result' => $result!==DiplomaticMessage::INVALID,
'reason' => $reason
]);
-74
View File
@@ -1,74 +0,0 @@
<?php
namespace sammo;
include('lib.php');
include('func.php');
WebUtil::requireAJAX();
$session = Session::requireGameLogin([]);
$userID = Session::getUserID();
$msgID = Util::getPost('msgID', 'int');
if($msgID === null){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 범위 입니다.'
]);
}
$lastMsgGet = Json::decode($session->lastMsgGet)??[];
$now = new \DateTime();
$delayTime = false;
if(count($lastMsgGet) >= 10){
try{
if($lastMsgGet[0] !== 'string'){
throw new \Exception('Why not string?');
}
$first = new \DateTime($lastMsgGet[0]);
$diff = $first->diff($now);
if($diff->days == 0 && $diff->h > 0 && $diff->i == 0 && $diff->s <= 5){
$delayTime = true;
}
array_shift($lastMsgGet);
}
catch(\Exception $e){
$lastMsgGet = [];
}
}
$lastMsgGet[] = $now;
$session->lastMsgGet = Json::encode($lastMsgGet);
if($delayTime){
sleep(1);
}
$session->setReadOnly();
list($generalID, $nationID, $generalName) = DB::db()->queryFirstList(
'select `no`, `nation`, `name` from `general` where owner = %i',
$userID
);
if($nationID === null){
Json::die([
'result'=>false,
'reason'=>'장수가 사망했습니다.'
]);
}
$reason = Message::deleteMsg($msgID, $generalID);
if($reason === null){
$result = [
'result'=>true,
'reason'=>'success'
];
}
else{
$result = [
'result'=>false,
'reason'=>$reason
];
}
Json::die($result);
-118
View File
@@ -1,118 +0,0 @@
<?php
namespace sammo;
include('lib.php');
include('func.php');
$session = Session::requireGameLogin([]);
$userID = Session::getUserID();
$reqTo = Util::getPost('to', 'int');
$reqType = Util::getPost('type', 'string');
if($reqTo === null){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 범위 입니다.'
]);
}
if($reqType === null || !in_array($reqType, ['private', 'public', 'national', 'diplomacy'])){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 타입입니다.'
]);
}
$lastMsgGet = Json::decode($session->lastMsgGet)??[];
$now = new \DateTime();
$delayTime = false;
if(count($lastMsgGet) >= 10){
try{
if($lastMsgGet[0] !== 'string'){
throw new \Exception('Why not string?');
}
$first = new \DateTime($lastMsgGet[0]);
$diff = $first->diff($now);
if($diff->days == 0 && $diff->h > 0 && $diff->i == 0 && $diff->s <= 1){
$delayTime = true;
}
array_shift($lastMsgGet);
}
catch(\Exception $e){
$lastMsgGet = [];
}
}
$lastMsgGet[] = $now;
$session->lastMsgGet = Json::encode($lastMsgGet);
if($delayTime){
sleep(1);
}
$session->setReadOnly();
$me = DB::db()->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID);
if($me === null){
Json::die([
'result'=>false,
'reason'=>'장수가 사망했습니다.'
]);
}
[$generalID, $nationID, $generalName] = [$me['no'], $me['nation'], $me['name']];
$permission = checkSecretPermission($me, false);
$result = [
'private'=>[],
'public'=>[],
'national'=>[],
'diplomacy'=>[],
'result'=>true,
'keepRecent'=>true,
'sequence'=>0,
'nationID'=>$nationID,
'generalName'=>$generalName,
];
$result['result'] = true;
$nextSequence = $reqTo;
if($reqType == 'private'){
$result['private'] = array_map(function(Message $msg) use (&$nextSequence){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
return $msg->toArray();
}, Message::getMessagesFromMailBoxOld($generalID, Message::MSGTYPE_PRIVATE, $reqTo, 15));
}
else if($reqType == 'public'){
$result['public'] = array_map(function(Message $msg)use (&$nextSequence){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
return $msg->toArray();
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_PUBLIC, Message::MSGTYPE_PUBLIC, $reqTo, 15));
}
else if($reqType == 'national'){
$result['national'] = array_map(function(Message $msg)use (&$nextSequence){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
return $msg->toArray();
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_NATIONAL, $reqTo, 15));
}
else{
$result['diplomacy'] = array_map(function(Message $msg)use (&$nextSequence, $permission){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
$values = $msg->toArray();
if($msg->dest->nationID != 0 && $permission < 3){
$values['text'] = '(외교 메시지입니다)';//TODO: 외교서신이라 읽을 수 없음을 보여줘야함
$values['option']['invalid'] = true;
}
return $values;
}, Message::getMessagesFromMailBoxOld(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_DIPLOMACY, $reqTo, 15));
}
Json::die($result);
-120
View File
@@ -1,120 +0,0 @@
<?php
namespace sammo;
include('lib.php');
include('func.php');
$session = Session::requireGameLogin([]);
$userID = Session::getUserID();
$reqSequence = Util::getPost('sequence', 'int', -1);
$lastMsgGet = Json::decode($session->lastMsgGet)??[];
$now = new \DateTime();
$delayTime = false;
if(count($lastMsgGet) >= 10){
try{
if(!is_string($lastMsgGet[0])){
throw new \Exception('Why not string?');
}
$first = new \DateTime($lastMsgGet[0]);
$diff = $first->diff($now);
if($diff->days == 0 && $diff->h > 0 && $diff->i == 0 && $diff->s <= 1){
$delayTime = true;
}
array_shift($lastMsgGet);
}
catch(\Exception $e){
$lastMsgGet = [];
}
}
$lastMsgGet[] = TimeUtil::now();
$session->lastMsgGet = Json::encode($lastMsgGet);
if($delayTime){
usleep(200);
}
$session->setReadOnly();
$db = DB::db();
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission FROM general WHERE `owner`=%i', $userID);
if($me === null){
Json::die([
'result'=>false,
'reason'=>'장수가 사망했습니다.'
]);
}
[$generalID, $nationID, $generalName] = [$me['no'], $me['nation'], $me['name']];
$permission = checkSecretPermission($me, false);
$result = [];
$result['result'] = true;
$result['keepRecent'] = false;
$nextSequence = $reqSequence;
$minSequence = $reqSequence;
$lastType = null;
$result['private'] = array_map(function(Message $msg) use (&$nextSequence, &$minSequence, &$lastType){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
if($msg->id <= $minSequence){
$minSequence = $msg->id;
$lastType = 'private';
}
return $msg->toArray();
}, Message::getMessagesFromMailBox($generalID, Message::MSGTYPE_PRIVATE, 15, $reqSequence));
$result['public'] = array_map(function(Message $msg)use (&$nextSequence, &$minSequence, &$lastType){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
if($msg->id <= $minSequence){
$minSequence = $msg->id;
$lastType = 'public';
}
return $msg->toArray();
}, Message::getMessagesFromMailBox(Message::MAILBOX_PUBLIC, Message::MSGTYPE_PUBLIC, 15, $reqSequence));
$result['national'] = array_map(function(Message $msg)use (&$nextSequence, &$minSequence, &$lastType){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
if($msg->id <= $minSequence){
$minSequence = $msg->id;
$lastType = 'national';
}
return $msg->toArray();
}, Message::getMessagesFromMailBox(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_NATIONAL, 15, $reqSequence));
$result['diplomacy']= array_map(function(Message $msg)use (&$nextSequence, &$minSequence, &$lastType, $permission){
if($msg->id > $nextSequence){
$nextSequence = $msg->id;
}
if($msg->id <= $minSequence){
$minSequence = $msg->id;
$lastType = 'diplomacy';
}
$values = $msg->toArray();
if($msg->dest->nationID != 0 && $permission < 3){
$values['text'] = '(외교 메시지입니다)';//TODO: 외교서신이라 읽을 수 없음을 보여줘야함
$values['option']['invalid'] = true;
}
return $values;
}, Message::getMessagesFromMailBox(Message::MAILBOX_NATIONAL + $nationID, Message::MSGTYPE_DIPLOMACY, 15, $reqSequence));
if($lastType !== null){
array_pop($result[$lastType]);
$result['keepRecent'] = true;
}
else if($reqSequence <= 0){
$result['keepRecent'] = true;
}
$result['sequence'] = $nextSequence;
$result['nationID'] = $nationID;
$result['generalName'] = $generalName;
Json::die($result);
-206
View File
@@ -1,206 +0,0 @@
<?php
namespace sammo;
include 'lib.php';
include 'func.php';
WebUtil::requireAJAX();
$post = Json::decode(Util::getPost('data', 'string', '{}'));
'@phan-var mixed[] $post';
$v = new Validator($post);
$v->rule('required', ['mailbox','text']);
$v->rule('integer', 'mailbox');
$v->rule('lengthMin', 'text', 1);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>$v->errorStr(),
'msgID'=>null
]);
}
$mailbox = (int)$post['mailbox'];
$text = trim(StringUtil::cutStringForWidth($post['text'], 199, ''));
$session = Session::requireGameLogin([
'msgID'=>null
]);
$userID = Session::getUserID();
//NOTE: 전송 메시지 시간 계산을 위해 Session을 쓰기 가능 상태로 열어둠.
increaseRefresh('서신전달', 1);
if(getBlockLevel() == 1 || getBlockLevel() == 3) {
Json::die([
'result' => false,
'reason' => '차단되었습니다.',
'msgID'=>null
]);
}
/**
* 메시지 전송 코드.
*
* TODO: 장기적으로 ajax는 한곳에 모을 필요가 있을 듯.
*/
$now = new \DateTime();
$unlimited = new \DateTime('9999-12-31');
$db = DB::db();
$me = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,penalty,permission,belong FROM general WHERE `owner`=%i', $userID);
if(!$me){
$session->logoutGame();
Json::die([
'result' => false,
'reason' => '로그인되지 않았습니다.',
'msgID' => null
]);
}
$con = checkLimit($me['con']);
if($con >= 2) {
Json::die([
'result' => false,
'reason' => '접속 제한입니다.',
'msgID' => null
]);
}
$me['icon'] = GetImageURL($me['imgsvr'], $me['picture']);
$permission = checkSecretPermission($me);
$srcNation = getNationStaticInfo($me['nation']);
$src = new MessageTarget($me['no'], $me['name'], $srcNation['nation'], $srcNation['name'], $srcNation['color'], $me['icon']);
// 전체 메세지
if($mailbox == Message::MAILBOX_PUBLIC) {
$msg = new Message(
Message::MSGTYPE_PUBLIC,
$src,
$src,
$text,
$now,
$unlimited,
[]
);
$msgID = $msg->send();
Json::die([
'result' => true,
'reason' => 'SUCCESS',
'msgID' => $msgID
]);
}
// 국가 메세지
if($mailbox >= Message::MAILBOX_NATIONAL) {
if($permission < 4){
$destNationID = $me['nation'];
}
else{
$destNationID = $mailbox - Message::MAILBOX_NATIONAL;
}
if($destNationID == $me['nation']){
$msgType = Message::MSGTYPE_NATIONAL;
}
else{
$msgType = Message::MSGTYPE_DIPLOMACY;
}
$destNation = getNationStaticInfo($destNationID);
$dest = new MessageTarget(0, '', $destNation['nation'], $destNation['name'], $destNation['color']);
$msg = new Message(
$msgType,
$src,
$dest,
$text,
$now,
$unlimited,
[]
);
$msgID = $msg->send();
Json::die([
'result' => true,
'reason' => 'SUCCESS',
'msgID' => $msgID
]);
}
// 개인 메세지
if($mailbox > 0) {
$lastMsg = new \DateTime($session->lastMsg??'0000-00-00');
$msg_interval = $now->getTimestamp() - $lastMsg->getTimestamp();
//NOTE: 여기서 유저 레벨을 구별할 코드가 필요할까?
if($msg_interval < 2){
Json::die([
'result' => false,
'reason' => '개인메세지는 2초당 1건만 보낼 수 있습니다!',
'msgID' => null
]);
}
$session->lastMsg = $now->format('Y-m-d H:i:s');
$destUser = $db->queryFirstRow('SELECT `no`,`name`,`nation`,`officer_level`,`con`,`picture`,`imgsvr`,permission,penalty FROM general WHERE `no`=%i',$mailbox);
if(!$destUser){
Json::die([
'result' => false,
'reason' => '존재하지 않는 유저입니다.',
'msgID' => null
]);
}
$destPermission = checkSecretPermission($destUser, false);
if($permission == 4 && $destPermission == 4 && $destUser['nation'] != $me['nation']){
Json::die([
'result' => false,
'reason' => '외교권자끼리는 메시지를 보낼 수 없습니다.',
'msgID' => null
]);
}
$destNation = getNationStaticInfo($destUser['nation']);
$dest = new MessageTarget(
$destUser['no'],
$destUser['name'],
$destNation['nation'],
$destNation['name'],
$destNation['color'],
GetImageURL($destUser['imgsvr'], $destUser['picture'])
);
$msg = new Message(
Message::MSGTYPE_PRIVATE,
$src,
$dest,
$text,
$now,
$unlimited,
[]
);
$msgID = $msg->send();
Json::die([
'result' => true,
'reason' => 'SUCCESS',
'msgID' => $msgID
]);
}
Json::die([
'result' => false,
'reason' => '알 수 없는 에러',
'msgID' => null
]);
+8 -9
View File
@@ -1,6 +1,10 @@
<?php
namespace sammo;
use sammo\Enums\GeneralLiteQueryMode;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\MessageType;
include "lib.php";
include "func.php";
@@ -43,12 +47,7 @@ if($destGeneralID==0){
$general->setVar('nation', $nationID);
}
else{
$general = General::createGeneralObjFromDB($destGeneralID, [
'name', 'leadership', 'strength', 'intel', 'gold','rice',
'troop','officer_level','npc','picture','imgsvr',
'permission','penalty','belong', 'crewtype',
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'aux',
], 1);
$general = General::createObjFromDB($destGeneralID);
if($general instanceof DummyGeneral){
Json::die([
@@ -226,8 +225,8 @@ function do추방(General $general, int $myOfficerLevel):?string{
}
else{
$betrayCnt = $general->getVar('betray');
$general->addExperience(-$general->getVar('experience')*0.1*$betrayCnt);
$general->addDedication(-$general->getVar('dedication')*0.1*$betrayCnt);
$general->addExperience(-$general->getVar('experience')*0.15*$betrayCnt);
$general->addDedication(-$general->getVar('dedication')*0.15*$betrayCnt);
$general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt);
}
@@ -268,7 +267,7 @@ function do추방(General $general, int $myOfficerLevel):?string{
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
);
$msg = new Message(
Message::MSGTYPE_PUBLIC,
MessageType::public,
$src,
$src,
$str,
+7
View File
@@ -1,6 +1,8 @@
<?php
namespace sammo;
use sammo\Enums\GeneralAccessLogColumn;
include "lib.php";
include "func.php";
@@ -86,6 +88,11 @@ $db->update('general', [
'owner'=>$userID,
'aux'=>Json::encode($genAux)
], 'owner <= 0 AND npc = 2 AND no = %i', $pick);
$db->insertIgnore('general_access_log', [
GeneralAccessLogColumn::generalID->value => $pick,
GeneralAccessLogColumn::userID->value => $userID,
GeneralAccessLogColumn::lastRefresh->value => $now,
]);
if(!$db->affectedRows()){
Json::die([
+2 -2
View File
@@ -56,7 +56,7 @@ if(file_exists(__DIR__.'/.htaccess')){
'scenarioName'=>$options['scenarioName'],
'turnterm'=>$options['turnterm'],
'fictionMode'=>($options['fiction']?'가상':'사실'),
'block_general_create'=>(!!$options['block_general_create']),
'block_general_create'=>Util::toInt($options['block_general_create']),
'npcMode'=>([0=>'불가',1=>'가능',2=>'선택 생성'][$options['npcmode']]),
'openDatetime'=>$reserved['date'],
'starttime'=>$options['starttime'],
@@ -90,7 +90,7 @@ $admin['scenario'] = $admin['scenario_text'];
$admin['userCnt'] = $genCnt;
$admin['npcCnt'] = $npcCnt;
$admin['nationCnt'] = $nationCnt;
$admin['block_general_create'] = !!$admin['block_general_create'];
$admin['block_general_create'] = $admin['block_general_create'];
$admin['npcMode'] = [0=>'불가',1=>'가능',2=>'선택 생성'][$admin['npcMode']];
$admin['fictionMode'] = $admin['fiction']?'가상':'사실';
+7 -3
View File
@@ -36,15 +36,19 @@ if($tnmt < 0 || $tnmt > 1){
}
$db = DB::db();
$me = General::createGeneralObjFromDB($generalID);
$me = General::createObjFromDB($generalID);
if($defence_train !== $me->getVar('defence_train')){
if($defence_train == 999){
$me->increaseVar('myset', -1);
$me->setVar('defence_train', $defence_train);
$me->increaseVarWithLimit('train', -3, 20);
$me->increaseVarWithLimit('atmos', -3, 20);
$affectedTrain = -3;
$affectedAtmos = -6;
$affectedTrain = $me->onCalcDomestic('changeDefenceTrain', "train{$defence_train}", $affectedTrain);
$affectedAtmos = $me->onCalcDomestic('changeDefenceTrain', "atmos{$defence_train}", $affectedAtmos);
$me->increaseVarWithLimit('train', $affectedTrain, 20, GameConst::$maxTrainByWar);
$me->increaseVarWithLimit('atmos', $affectedAtmos, 20, GameConst::$maxAtmosByWar);
}
else{
$me->increaseVar('myset', -1);
+5 -2
View File
@@ -39,7 +39,10 @@ if (!$data || !is_array($data)) {
$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'];
@@ -82,7 +85,7 @@ function applyNationPolicy($policy, $nationID, $generalName): ?string
return "{$troopID}는 국가의 부대가 아닙니다.";
}
if ($troopCache[$troopID] != 'Neutral') {
return "부대({$troopID}는 하나의 역할만 지정할 수 있습니다.";
return "부대({$troopID})는 하나의 역할만 지정할 수 있습니다.";
}
if (!is_array($troopTarget) || count($troopTarget) != 2) {
return "{$troopID}의 입력양식이 올바르지 않습니다.";
+318 -214
View File
@@ -1,4 +1,5 @@
<?php
namespace sammo;
use Ds\Map;
@@ -15,48 +16,48 @@ $userID = Session::getUserID();
increaseRefresh("시뮬레이터", 0);
$query = Util::getPost('query');
if($query === null){
if ($query === null) {
Json::die([
'result'=>false,
'reason'=>'입력값이 없습니다.'
'result' => false,
'reason' => '입력값이 없습니다.'
]);
}
$action = Util::getPost('action');
if($action === null || !in_array($action, ['reorder', 'battle'])){
if ($action === null || !in_array($action, ['reorder', 'battle'])) {
Json::die([
'result'=>false,
'reason'=>'원하는 동작이 지정되지 않았습니다.'
'result' => false,
'reason' => '원하는 동작이 지정되지 않았습니다.'
]);
}
$query = Json::decode($query);
if($query === null){
if ($query === null) {
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 JSON입니다.'
'result' => false,
'reason' => '올바르지 않은 JSON입니다.'
]);
}
$defaultCheck = [
'required'=>[
'required' => [
'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation',
'year', 'month', 'repeatCnt'
],
'integer'=>[
'year','month','repeatCnt'
'integer' => [
'year', 'month', 'repeatCnt'
],
'between'=>[
'between' => [
['month', [1, 12]]
],
'in'=>[
'in' => [
['repeatCnt', [1, 1000]]
],
'min'=>[
'min' => [
['year', 0]
],
'array'=>[
'array' => [
'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation'
],
@@ -64,10 +65,10 @@ $defaultCheck = [
$v = new Validator($query);
$v->rules($defaultCheck);
if(!$v->validate()){
if (!$v->validate()) {
Json::die([
'result'=>false,
'reason'=>$v->errorStr()
'result' => false,
'reason' => $v->errorStr()
]);
}
@@ -84,21 +85,112 @@ $rawDefenderList = $query['defenderGenerals'];
$rawDefenderCity = $query['defenderCity'];
$rawDefenderNation = $query['defenderNation'];
$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 = [
'required'=>[
'required' => [
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item',
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'recent_war', 'warnum', 'killnum', 'killcrew',
],
'integer'=>[
'integer' => [
'no', 'nation', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp',
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'warnum', 'killnum', 'killcrew',
],
'min'=>[
'min' => [
['no', 1],
['nation', 1],
['crew', 0],
@@ -117,14 +209,14 @@ $generalCheck = [
['killnum', 0],
['killcrew', 0],
],
'between'=>[
'between' => [
['train', [40, GameConst::$maxTrainByWar]],
['atmos', [40, GameConst::$maxAtmosByWar]],
['explevel', [0, 300]],
['injury', [0, 80]],
['officer_level', [1, 12]]
],
'in'=>[
'in' => [
['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)],
['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)],
['crewtype', array_keys(GameUnitConst::all())],
@@ -132,162 +224,138 @@ $generalCheck = [
['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])],
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
],
'array' => ['inheritBuff'],
];
$inheritBuffCheck = [
'between' => [
[TriggerInheritBuff::WAR_AVOID_RATIO, [0, 5]],
[TriggerInheritBuff::WAR_CRITICAL_RATIO, [0, 5]],
[TriggerInheritBuff::WAR_MAGIC_TRIAL_PROB, [0, 5]],
[TriggerInheritBuff::OPPOSE_WAR_AVOID_RATIO, [0, 5]],
[TriggerInheritBuff::OPPOSE_WAR_CRITICAL_RATIO, [0, 5]],
[TriggerInheritBuff::OPPOSE_WAR_MAGIC_TRIAL_PROB, [0, 5]],
]
];
if(!$warSeed){
$warSeed = bin2hex(random_bytes(16));
}
else {
$repeatCnt = 1;
}
$tmpRNG = new RandUtil(new LiteHashDRBG($warSeed));
$v = new Validator($rawAttacker);
$v->rules($generalCheck);
if(!$v->validate()){
if (!$v->validate()) {
Json::die([
'result'=>false,
'reason'=>'[출병자]'.$v->errorStr()
'result' => false,
'reason' => '[출병자]' . $v->errorStr()
]);
}
$rawAttacker['owner'] = 0;
$defenderList = [];
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
$v = new Validator($rawDefenderGeneral);
$v->rules($generalCheck);
if(!$v->validate()){
$idx+=1;
$rawAttacker['aux'] = [];
if (key_exists('inheritBuff', $rawAttacker)) {
$v = new Validator($rawAttacker['inheritBuff']);
$v->rules($inheritBuffCheck);
if (!$v->validate()) {
Json::die([
'result'=>false,
'reason'=>"[수비자{$idx}]".$v->errorStr()
'result' => false,
'reason' => '[출병자]' . $v->errorStr()
]);
}
$rawAttacker['aux']['inheritBuff'] = $rawAttacker['inheritBuff'];
}
$rawAttacker['aux'] = Json::encode($rawAttacker['aux']);
$rawAttacker['owner'] = 0;
$attackerGeneral = new General($rawAttacker, extractRankVar($rawAttacker), null, $rawAttackerCity, $rawAttackerNation, $year, $month);
$attacker = new WarUnitGeneral(
$tmpRNG,
$attackerGeneral,
$rawAttackerNation,
true
);
/** @var WarUnit[] */
$defenderList = [];
foreach ($rawDefenderList as $idx => $rawDefenderGeneral) {
$v = new Validator($rawDefenderGeneral);
$v->rules($generalCheck);
if (!$v->validate()) {
$idx += 1;
Json::die([
'result' => false,
'reason' => "[수비자{$idx}]" . $v->errorStr()
]);
}
$rawDefenderGeneral['aux'] = [];
if (key_exists('inheritBuff', $rawDefenderGeneral)) {
$v = new Validator($rawDefenderGeneral['inheritBuff']);
$v->rules($inheritBuffCheck);
if (!$v->validate()) {
$idx += 1;
Json::die([
'result' => false,
'reason' => "[수비자{$idx}]" . $v->errorStr()
]);
}
$rawDefenderGeneral['aux']['inheritBuff'] = $rawDefenderGeneral['inheritBuff'];
}
$rawDefenderGeneral['aux'] = Json::encode($rawDefenderGeneral['aux']);
$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 = [
'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()
]);
}
if($action == 'reorder'){
usort($defenderList, function(General $lhs, General $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
usort($defenderList, function (WarUnit $lhs, WarUnit $rhs) use ($attacker) {
return - (extractBattleOrder($lhs, $attacker) <=> extractBattleOrder($rhs, $attacker));
});
$order = [];
foreach($defenderList as $defenderGeneral){
$order[] = $defenderGeneral->getID();
foreach ($defenderList as $defender) {
$order[] = $defender->getGeneral()->getID();
}
Json::die([
'result'=>true,
'reason'=>'success',
'order'=>$order
'result' => true,
'reason' => 'success',
'order' => $order
]);
}
usort($defenderList, function(General $lhs, General $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
});
$rawDefenderList = array_map(function(General $general){
return $general->getRaw();
}, $defenderList);
$rawDefenderList = [];
foreach($defenderList as $unit){
if(extractBattleOrder($unit, $attacker) <= 0){
continue;
}
$rawDefenderList[] = $unit->getRaw();
}
unset($defenderList);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$startYear = $gameStor->startyear;
$cityRate = Util::round(($year - $startYear) / 1.5) + 60;
function extractRankVar(array $rawVal):Map{
function extractRankVar(array $rawVal): Map
{
$rankVars = new Map;
foreach($rawVal as $rawKey=>$rawVal){
foreach ($rawVal as $rawKey => $rawVal) {
$key = RankColumn::tryFrom($rawKey);
if($key === null){
if ($key === null) {
continue;
}
$rankVars[$key] = $rawVal;
@@ -296,86 +364,113 @@ function extractRankVar(array $rawVal):Map{
}
function simulateBattle(
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$startYear, $year, $month, $cityRate
){
$rawAttacker,
$rawAttackerCity,
$rawAttackerNation,
$rawDefenderList,
$rawDefenderCity,
$rawDefenderNation,
$startYear,
$year,
$month,
$warSeed
) {
if (!$warSeed) {
$warSeed = bin2hex(random_bytes(16));
}
$warSeed = bin2hex(random_bytes(16));
$warRng = new RandUtil(new LiteHashDRBG($warSeed));
$attackerGeneral = new General($rawAttacker, extractRankVar($rawAttacker), null, $rawAttackerCity, $rawAttackerNation, $year, $month);
$attacker = new WarUnitGeneral(
$warRng,
new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month),
$attackerGeneral,
$rawAttackerNation,
true
);
$city = new WarUnitCity($warRng, $rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
$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();
$battleResult = [];
$attackerRice = $rawAttacker['rice'];
$attackerRice = $attacker->getGeneral()->getVar('rice');
$defenderRice = 0;
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
use ($warRng, $iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
if($prevDefender !== null){
$getNextDefender = function (?WarUnit $prevDefender, bool $reqNext)
use ($iterDefender, &$battleResult, &$defenderRice, $attacker): ?WarUnit {
if ($prevDefender !== null) {
$prevDefender->getLogger()->rollback();
$battleResult[] = $prevDefender;
if($prevDefender instanceof WarUnitGeneral){
if ($prevDefender instanceof WarUnitGeneral) {
$defenderRice -= $prevDefender->getVar('rice');
}
}
if(!$reqNext){
if (!$reqNext) {
return null;
}
if(!$iterDefender->valid()){
if (!$iterDefender->valid()) {
return null;
}
$defenderObj = new General($iterDefender->current(), extractRankVar($iterDefender->current()), $rawDefenderCity, $rawDefenderNation, $year, $month);
if(extractBattleOrder($defenderObj) <= 0){
/** @var WarUnit */
$defender = $iterDefender->current();
if (extractBattleOrder($defender, $attacker) <= 0) {
return null;
}
$defenderRice += $defenderObj->getVar('rice');
if($defender instanceof WarUnitGeneral){
$defenderRice += $defender->getVar('rice');
}
$retVal = new WarUnitGeneral(
$warRng,
$defenderObj,
$rawDefenderNation,
false
);
$iterDefender->next();
return $retVal;
return $defender;
};
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear);
$rawDefenderCity = $city->getRaw();
$updateAttackerNation = [];
$updateDefenderNation = [];
$conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city);
$attackerRice -= $attacker->getVar('rice');
if($city->getPhase() > 0){
if ($city->getPhase() > 0) {
$rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice;
$rice *= getTechCost($rawDefenderNation['tech']);
$rice *= $cityRate / 100 - 0.2;
$rice *= getTechCost($city->getRawNation()['tech']);
$rice *= $city->getCityTrainAtmos() / 100 - 0.2;
Util::setRound($rice);
$defenderRice += $rice;
}
$totalDead = $attacker->getKilled() + $attacker->getDead();
$attackerCityDead = $totalDead * 0.4;
$defenderCityDead = $totalDead * 0.6;
//$attackerCityDead = $totalDead * 0.4;
//$defenderCityDead = $totalDead * 0.6;
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
}
@@ -401,14 +496,26 @@ $avgWar = 0;
$attackerActivatedSkills = [];
$defendersActivatedSkills = [];
foreach(Util::range($repeatCnt) as $repeatIdx){
foreach (Util::range($repeatCnt) as $repeatIdx) {
if($repeatIdx > 0){
$warSeed = bin2hex(random_bytes(16));
}
/** @var WarUnit $attacker */
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$startYear, $year, $month, $cityRate
$rawAttacker,
$rawAttackerCity,
$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));
}, $attacker->getLogger()->rollback());
@@ -431,48 +538,45 @@ foreach(Util::range($repeatCnt) as $repeatIdx){
$avgWar += count($battleResult) / $repeatCnt;
foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){
if(!key_exists($skillName, $attackerActivatedSkills)){
foreach ($attacker->getActivatedSkillLog() as $skillName => $skillCnt) {
if (!key_exists($skillName, $attackerActivatedSkills)) {
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
}
else{
} else {
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
}
}
foreach($battleResult as $idx=>$defender){
while($idx >= count($defendersActivatedSkills)){
foreach ($battleResult as $idx => $defender) {
while ($idx >= count($defendersActivatedSkills)) {
$defendersActivatedSkills[] = [];
}
$activatedSkills = &$defendersActivatedSkills[$idx];
foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
if(!key_exists($skillName, $activatedSkills)){
foreach ($defender->getActivatedSkillLog() as $skillName => $skillCnt) {
if (!key_exists($skillName, $activatedSkills)) {
$activatedSkills[$skillName] = $skillCnt / $repeatCnt;
}
else{
} else {
$activatedSkills[$skillName] += $skillCnt / $repeatCnt;
}
}
}
}
Json::die([
'result'=>true,
'datetime'=>$rawAttacker['turntime'],
'reason'=>'success',
'lastWarLog'=>$lastWarLog,
'avgWar'=>$avgWar,
'phase'=>$avgPhase,
'killed'=>$attackerKilled,
'maxKilled'=>$attackerMaxKilled,
'minKilled'=>$attackerMinKilled,
'dead'=>$attackerDead,
'maxDead'=>$attackerMaxDead,
'minDead'=>$attackerMinDead,
'attackerRice'=>$attackerAvgRice,
'defenderRice'=>$defenderAvgRice,
'attackerSkills'=>$attackerActivatedSkills,
'defendersSkills'=>$defendersActivatedSkills,
'result' => true,
'datetime' => $rawAttacker['turntime'],
'reason' => 'success',
'lastWarLog' => $lastWarLog,
'avgWar' => $avgWar,
'phase' => $avgPhase,
'killed' => $attackerKilled,
'maxKilled' => $attackerMaxKilled,
'minKilled' => $attackerMinKilled,
'dead' => $attackerDead,
'maxDead' => $attackerMaxDead,
'minDead' => $attackerMinDead,
'attackerRice' => $attackerAvgRice,
'defenderRice' => $defenderAvgRice,
'attackerSkills' => $attackerActivatedSkills,
'defendersSkills' => $defendersActivatedSkills,
]);
-172
View File
@@ -1,172 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
// $btn, $name, $troop
$action = Util::getPost('action');
$name = Util::getPost('name');
$gen = Util::getPost('gen', 'int');
$troop = Util::getPost('troop', 'int');
//로그인 검사
$session = Session::requireGameLogin([])->setReadOnly();
$userID = $session::getUserID();
increaseRefresh("부대명령", 0);
$db = DB::db();
$me = $db->queryFirstRow('SELECT `no`, name, nation, troop FROM general WHERE `owner`=%i', $userID);
$generalID = $me['no'];
$nationID = $me['nation'];
if($action == '부대창설'){
$name = StringUtil::neutralize($name);
if(!$name){
Json::die([
'result'=>false,
'reason'=>'부대 이름이 없습니다.'
]);
}
if($me['troop'] != 0){
Json::die([
'result'=>false,
'reason'=>'이미 부대에 가입해있습니다.'
]);
}
$db->insert('troop',[
'troop_leader'=>$generalID,
'name'=>$name,
'nation'=>$nationID,
]);
$db->update('general', [
'troop'=>$generalID,
], 'no=%i',$generalID);
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
if($action == '부대변경'){
$name = StringUtil::neutralize($name);
if(!$name){
Json::die([
'result'=>false,
'reason'=>'부대 이름이 없습니다.'
]);
}
$db->update('troop', [
'name'=>$name
], 'troop_leader=%i',$generalID);
if($db->affectedRows() == 0){
Json::die([
'result'=>false,
'reason'=>'부대장이 아닙니다.'
]);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
if($action == '부대추방'){
if (!$gen){
Json::die([
'result'=>false,
'reason'=>'장수를 지정해야 합니다.'
]);
}
$db->update('general', [
'troop'=>0
], 'no=%i AND troop = %i', $gen, $generalID);
if($db->affectedRows() == 0){
Json::die([
'result'=>false,
'reason'=>'부대장이 아니거나, 장수를 잘못 지정했습니다.'
]);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
if ($action == '부대가입') {
if(!$troop){
Json::die([
'result'=>false,
'reason'=>'부대를 지정해야 합니다.'
]);
}
if($me['troop'] === $generalID){
Json::die([
'result'=>false,
'reason'=>'부대장입니다.'
]);
}
$troopExists = $db->queryFirstField('SELECT `troop_leader` FROM `troop` WHERE `troop_leader` = %i AND `nation` = %i', $troop, $nationID);
if (!$troopExists) {
Json::die([
'result'=>false,
'reason'=>'올바른 부대장이 아닙니다.'
]);
}
$db->update('general', [
'troop'=>$troop
], 'no=%i', $generalID);
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
if($action == "부대탈퇴") {
if($me['troop'] == 0){
Json::die([
'result'=>false,
'reason'=>'부대에 속해있지 않습니다.'
]);
}
//부대장일 경우
if($me['troop'] === $generalID){
$db->update('general', [
'troop'=>0
], 'troop=%i',$generalID);
$db->delete('troop', 'troop_leader=%i', $generalID);
}
else{
$db->update('general', [
'troop'=>0
], 'no=%i', $generalID);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 명령입니다.'
]);
+1 -1
View File
@@ -66,7 +66,7 @@ if(!$ownerInfo){
$info = Json::decode($info);
$generalObj = General::createGeneralObjFromDB($generalID);
$generalObj = General::createObjFromDB($generalID);
$oldGeneralName = $generalObj->getName();
$db->update('select_pool', [
'general_id'=>-$generalID,
+22
View File
@@ -0,0 +1,22 @@
function getCityPosition(){
return {"1":["서량",127,101],"2":["무도",127,222],"3":["성도",127,344],"4":["건녕",127,384],"5":["안정",167,141],"6":["한중",167,222],"7":["검각",167,263],"8":["자동",167,303],"9":["강주",167,344],"10":["장안",208,182],"11":["영안",208,384],"12":["홍농",248,182],"13":["완",248,222],"14":["양양",248,303],"15":["강릉",248,344],"16":["무릉",248,384],"17":["영릉",248,425],"18":["낙양",289,182],"19":["신야",289,263],"20":["강하",289,344],"21":["장사",289,384],"22":["계양",289,425],"23":["남해",289,465],"24":["업",329,101],"25":["진유",329,141],"26":["허창",329,182],"27":["여남",329,222],"28":["시상",329,344],"29":["평원",370,60],"30":["복양",370,101],"31":["초",370,141],"32":["수춘",370,222],"33":["단양",370,263],"34":["여강",370,303],"35":["계",410,20],"36":["남피",410,60],"37":["소패",410,141],"38":["건업",410,222],"39":["북평",451,20],"40":["북해",451,101],"41":["하비",451,141],"42":["광릉",451,182],"43":["오",451,263],"44":["회계",451,303],"45":["양평",491,20],"46":["국내",532,20],"47":["한",532,60],"48":["사비",532,101],"49":["매소",572,60],"50":["서라벌",572,101],"51":["운남",127,425],"52":["천수",127,182],"53":["졸본",572,20]};
}
function formatCityInfo(city) {
var regionMap = {"하북":1,"1":"하북","중원":2,"2":"중원","서북":3,"3":"서북","서촉":4,"4":"서촉","남중":5,"5":"남중","초":6,"6":"초","오월":7,"7":"오월","동이":8,"8":"동이"};
var levelMap = {"수":1,"1":"수","진":2,"2":"진","관":3,"3":"관","이":4,"4":"이","소":5,"5":"소","중":6,"6":"중","대":7,"7":"대","특":8,"8":"특"};
var region_str = regionMap[city.region];
var level_str = levelMap[city.level];
city.text = '【' + region_str + '|' + level_str + '】' + city.name;
city.region_str = region_str;
city.level_str = level_str;
return city;
}
+5 -2
View File
@@ -9,6 +9,9 @@ $loader->addClassMap((function () {
$d_settingMap = [];
foreach (glob(__DIR__.'/d_setting/*.orig.php') as $filepath) {
$filepath = str_replace('.orig.php', '.php', $filepath);
if(!file_exists($filepath)) {
continue;
}
$filename = basename($filepath);
$classname = explode('.', $filename)[0];
$d_settingMap['sammo\\'.$classname] = $filepath;
@@ -63,8 +66,8 @@ function prepareDir(string $dirPath, bool $forceCreate=true):bool{
if(!unlink($dirPath)){
return false;
}
return mkdir($dirPath);
return mkdir($dirPath, 0775);
}
return mkdir($dirPath, 0777, true);
return mkdir($dirPath, 0775, true);
}
+455
View File
@@ -0,0 +1,455 @@
<?php
namespace sammo;
use sammo\DTO\VoteInfo;
use sammo\Enums\GeneralQueryMode;
include "lib.php";
include "func.php";
$session = Session::requireLogin()->loginGame()->setReadOnly();
$userID = Session::getUserID();
increaseRefresh("메인", 1);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if (!$userID) {
header('Location:..');
die();
}
//턴 실행.
TurnExecutionHelper::executeAllCommand();
if (!$session->isGameLoggedIn()) {
header('Location:..');
die();
}
$me = $db->queryFirstRow(
'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
);
//그새 사망이면
if ($me === null) {
$session->logoutGame();
header('Location: ../');
die();
}
$gameStor->cacheAll(true);
if ($me['newmsg'] == 1 || $me['newvote'] == 1) {
$db->update('general', [
'newmsg' => 0,
'newvote' => 0
], 'owner=%i', $userID);
}
$plock = boolval($db->queryFirstField('SELECT plock FROM plock WHERE `type`="GAME" LIMIT 1'));
$limitState = checkLimit($me['refresh_score']);
if ($limitState >= 2) {
printLimitMsg($me['turntime']);
exit();
}
$generalObj = General::createObjFromDB($me['no'], null, GeneralQueryMode::FullWithAccessLog);
$generalObj->setRawCity($db->queryFirstRow('SELECT * FROM city WHERE city = %i', $generalObj->getCityID()));
$scenario = $gameStor->scenario_text;
$nationID = $generalObj->getNationID();
if ($nationID) {
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->cacheAll();
}
if ($gameStor->extended_general == 0) {
$extend = "표준";
} else {
$extend = "확장";
}
if ($gameStor->fiction == 0) {
$fiction = "사실";
} else {
$fiction = "가상";
}
if ($gameStor->npcmode == 0) {
$npcmode = "불가능";
} else if ($gameStor->npcmode == 1) {
$npcmode = "가능";
} else {
$npcmode = "선택 생성";
}
$color = "cyan";
$serverName = UniqueConst::$serverName;
$serverCnt = $gameStor->server_cnt;
$auctionCount = $db->queryFirstField('SELECT count(*) FROM ng_auction WHERE finished = 0');
$isTournamentActive = $gameStor->tournament > 0;
$isTournamentApplicationOpen = $gameStor->tournament == 1;
$isBettingActive = $gameStor->tournament == 6;
$myNationStatic = getNationStaticInfo($generalObj->getNationID());
$nationColorType = substr($myNationStatic['color'] ?? '#000000', 1);
$autorunUser = ($gameStor->autorun_user) ?? [];
$otherTextInfo = [];
if ($gameStor->join_mode == 'onlyRandom') {
$otherTextInfo[] = '랜덤 임관 전용';
}
if ($autorunUser['limit_minutes'] ?? false) {
$otherTextInfo[] = getAutorunInfo($autorunUser);
}
if (!$otherTextInfo) {
$otherTextInfo = '표준';
} else {
$otherTextInfo = join(', ', $otherTextInfo);
}
$lastVoteID = $gameStor->lastVote;
$lastVote = null;
if ($lastVoteID) {
$voteStor = KVStorage::getStorage($db, 'vote');
$lastVote = VoteInfo::fromArray($voteStor->getValue("vote_{$lastVoteID}"));
if ($lastVote->endDate && $lastVote->endDate < TimeUtil::now()) {
$lastVote = null;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title><?= $serverName ?>: 메인</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=500" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('d_shared/base_map.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('vue', 'v_main', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/map.css') ?>
<?= WebUtil::printStaticValues([
//deprecated, staticValues를 이용할 것
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'staticValues' => [
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'mapName' => GameConst::$mapName,
'unitSet' => GameConst::$unitSet,
]
]) ?>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
</head>
<body class="img_back sam-color-<?= $nationColorType ?>">
<div id="container" class="bg0">
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></button></div>
</div>
<div class="tb_layout row gx-0">
<div id="server_title" class="row py-2 center">
<h3>삼국지 모의전투 HiDCHe <?= $serverName . $serverCnt ?>기 <span class="avoid-wrap">(<font color=cyan><?= $scenario ?></font>)</span></h3>
</div>
<div class="row center gx-0">
<div class="s-border-t col py-2 col-8 col-lg-4" style="color:<?= $color ?>;">
<?= $scenario ?>
</div>
<div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
NPC 수, 상성 : <?= $extend ?>,<?= $fiction ?>
</div>
<div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
NPC선택 : <?= $npcmode ?>
</div>
<div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
토너먼트 : <?= getTournamentTermText($gameStor->turnterm) ?>
</div>
<div class="s-border-t col py-2 col-4 col-lg-2" style="color:<?= $color ?>;">
기타 설정: <?= $otherTextInfo ?>
</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-lg-2">전체 접속자 수 : <?= $gameStor->online_user_cnt ?> 명</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-lg-4"><?= info(3) ?></div>
<div class="s-border-t py-2 col col-6 col-lg-4">
<?php if ($isTournamentActive) : ?>
↑<span style='color:cyan'><?= (['전력전', '통솔전', '일기토', '설전',])[$gameStor->tnmt_type] ?? '' ?> <?= getTournament($gameStor->tournament) ?> <?= getTournamentTime() ?></span>↑
<?php else : ?>
<span style='color:magenta'>현재 토너먼트 경기 없음</span>
<?php endif; ?>
</div>
<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>
<div class="s-border-t py-2 col col-6 col-lg-2">
<?php if ($auctionCount > 0) : ?>
<span style='color:cyan'><?= $auctionCount ?>건</span> 거래 진행중
<?php else : ?>
<span style='color:magenta'>진행중 거래 없음</span>
<?php endif; ?>
</div>
<div class="s-border-t py-2 col col-6 col-lg-4 vote-cell">
<?php
?>
<?php if ($lastVote === null) : ?>
<span style='color:magenta'>진행중 설문 없음</span>
<?php else : ?>
<span style='color:cyan'>설문 진행중</span> : <span><?= $lastVote->title ?></span>
<?php endif; ?>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">접속중인 국가: <?= $gameStor->online_nation ?></div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">운영자 메세지 : <span style='color:yellow;'><?= $gameStor->msg ?></span></div>
</div>
<div class="row gx-0">
<div class="col s-border-t py-2" id="nation-msg-position">
<div class="px-2">【 국가방침 】</div>
<div id='nation-msg-box'>
<div id='nation-msg'><?= nationMsg($generalObj) ?></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">
【 접속자 】<?= onlinegen($generalObj) ?>
</div>
</div>
<?php if ($session->userGrade >= 5) : ?>
<div class="row">
<div class="col">
<a href='_admin1.php' target='_blank'><button type='button'>게임관리</button></a>
<a href='_admin2.php' target='_blank'><button type='button'>회원관리</button></a>
<a href='_admin4.php' target='_blank'><button type='button'>멀티관리</button></a>
<a href='_admin5.php' target='_blank'><button type='button'>일제정보</button></a>
<a href='_admin7.php' target='_blank'><button type='button'>로그정보</button></a>
<a href='_admin8.php' target='_blank'><button type='button'>외교정보</button></a>
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php elseif ($session->userGrade == 4) : ?>
<div class="row">
<div class="col">
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php endif; ?>
<div id="map_view" class="gx-0">
<div id="mapZone" class="view-item"><?= getMapHtml() ?></div>
<div class="view-item" id="reservedCommandZone">
<div id="reservedCommandList"></div>
<div id="actionMiniPlate" class="gx-0 row">
<div class="col">
<div class="gx-1 row">
<div class="col-8 d-grid"><button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button></div>
<div class="col-4 d-grid"><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></div>
</div>
</div>
</div>
</div>
<div id="cityInfo" class="view-item" style="border:none;text-align:center;"><?= cityInfo($generalObj) ?></div>
<div id="nation-position"><?php myNationInfo($generalObj); ?></div>
<div id="general-position"><?php generalInfo($generalObj); ?></div>
<div id="generalCommandButton" class="row gx-0">
<div class="buttonPlate bg2">
<?= commandButton([
'splitBtnBegin' => '<div class="btn-group">',
'splitBtnEnd' => '</div>',
'splitZoneSign' => '<button type="button" class="btn btn-sammo-nation dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"><span class="visually-hidden">Toggle Dropdown</span></button>',
'splitZoneBegin' => '<ul class="dropdown-menu dropdown-menu-end">',
'splitZoneEnd' => '</ul>',
'splitSubBtnBegin' => '<li>',
'splitSubBtnEnd' => '</li>',
'btnClass' => 'btn btn-sammo-nation',
'btnSplitClass' => 'dropdown-item',
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive
])
?></div>
</div>
</div>
</div>
<div id="actionMiniPlateSub" class="gx-0 row">
<div class="col">
<div class="gx-1 row">
<div class="col-3 d-grid"><button type='button' class="btn btn-dark" onclick="scrollHardTo('reservedCommandList')">명령으로</button></div>
<div class="col-5 d-grid"><button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button></div>
<div class="col-4 d-grid"><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col-lg-6" id="general_public_record-position">
<div class="bg1 center s-border-tb"><b>장수 동향</b></div>
<div id="general_public_record" style="text-align:left;"><?= formatHistoryToHTML(getGlobalActionLogRecent(15)) ?></div>
</div>
<div class="col-lg-6" id="general_log-position">
<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>
<div class="col-12" id="world_history-position">
<div class="bg1 center s-border-tb"><b>중원 정세</b></div>
<div id="world_history" colspan=2 style="text-align:left;"><?= formatHistoryToHTML(getGlobalHistoryLogRecent(15)) ?></div>
</div>
</div>
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></div>
<div id="message_board" class="row gx-0">
<div class="message_input_form bg0 gx-0 row">
<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>
</div>
<div id="msg_input-col" class="col-12 col-lg-8 d-grid">
<input type="text" id="msg_input" maxlength="99" class="form-control">
</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 class="col-lg-6 board_side bg0"><a id="public_talk_position"></a>
<div class="board_header bg0">전체 메시지(최고99자)</div>
<section class="public_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="public">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-lg-6 board_side bg0"><a id="national_talk_position"></a>
<div class="board_header bg0">국가 메시지(최고99자)</div>
<section class="national_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="national">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-lg-6 board_side bg0"><a id="private_talk_position"></a>
<div class="board_header bg0">개인 메시지(최고99자)</div>
<section class="private_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="private">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-lg-6 board_side bg0"><a id="diplomacy_talk_position"></a>
<div class="board_header bg0">외교 메시지(최고99자)</div>
<section class="diplomacy_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="diplomacy">이전 메시지 불러오기</button></div>
</section>
</div>
</div>
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></div><?= banner() ?>
</div>
</div>
<?php
if ($limitState == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!");
}
if ($me['newmsg'] == 1) {
MessageBox("새로운 서신이 도착했습니다!");
}
if ($me['newvote'] == 1) {
$develcost = $gameStor->develcost * 5;
MessageBox("설문조사에 참여하시면 금{$develcost}과 유니크템을 드립니다! (우측 상단 설문조사 메뉴)");
}
?>
</div>
<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="collapse navbar-collapse">
<ul class="navbar-nav me-auto mx-auto">
<li class="nav-item dropup">
<div class="dropdown-toggle text-white btn btn-sammo-base2" id="navbarGlobal" role="button" data-bs-toggle="dropdown" aria-expanded="false">
외부 메뉴
</div>
<ul class="dropdown-menu dropdown-menu-start" aria-labelledby="navbarGlobal" id="navbarGlobalItems">
<?= allButton($gameStor->npcmode == 1, ['btnBegin' => '<li>', 'btnEnd' => '</li>', 'btnClass' => 'dropdown-item']) ?>
</ul>
</li>
<li class="nav-item dropup">
<div class="dropdown-toggle btn btn-sammo-nation" id="navbarNation" role="button" data-bs-toggle="dropdown" aria-expanded="false">
국가 메뉴
</div>
<ul class="dropdown-menu" aria-labelledby="navbarNation" id="navbarNationItems">
<?= commandButton([
'btnBegin' => '<li>',
'btnEnd' => '</li>',
'splitMainBegin' => '<div class="d-none">',
'splitMainEnd' => '</div>',
'splitSubBtnBegin' => '<li>',
'splitSubBtnEnd' => '</li>',
'btnClass' => 'dropdown-item',
'btnSplitClass' => 'dropdown-item',
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive
]) ?>
</ul>
</li>
<li class="nav-item dropup">
<div class="dropdown-toggle text-white btn btn-dark" id="navbarQuick" role="button" data-bs-toggle="dropdown" aria-expanded="false">
빠른 이동
</div>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown" id="navbarQuickItems">
<li><a class="dropdown-item disabled">국가 정보</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('nation-msg-position')" class="dropdown-item">방침</button></li>
<li><button type="button" onclick="scrollHardTo('reservedCommandList')" class="dropdown-item">명령</button></li>
<li><button type="button" onclick="scrollHardTo('nation-position')" class="dropdown-item">국가</button></li>
<li><button type="button" onclick="scrollHardTo('general-position')" class="dropdown-item">장수</button></li>
<li><button type="button" onclick="scrollHardTo('cityInfo')" class="dropdown-item">도시</button></li>
<li><a class="dropdown-item disabled">동향 정보</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('mapZone')" class="dropdown-item">지도</button></li>
<li><button type="button" onclick="scrollHardTo('general_public_record-position')" class="dropdown-item">동향</button></li>
<li><button type="button" onclick="scrollHardTo('general_log-position')" class="dropdown-item">개인</button></li>
<li><button type="button" onclick="scrollHardTo('world_history-position')" class="dropdown-item">정세</button></li>
<li><span>&nbsp;</span></li>
<li><a class="dropdown-item disabled">메시지</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('public_talk_position')" class="dropdown-item">전체</button></li>
<li><button type="button" onclick="scrollHardTo('national_talk_position')" class="dropdown-item">국가</button></li>
<li><button type="button" onclick="scrollHardTo('private_talk_position')" class="dropdown-item">개인</button></li>
<li><button type="button" onclick="scrollHardTo('diplomacy_talk_position')" class="dropdown-item">외교</button></li>
<li><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></li>
</ul>
</li>
<li class="nav-item">
<a class="refreshPage btn btn-sammo-base2 text-white" role="button">갱신</a>
</li>
</ul>
</div>
</div>
</nav>
</body>
</html>
+96 -76
View File
@@ -2,6 +2,8 @@
namespace sammo;
use sammo\Enums\EventTarget;
use sammo\Enums\GeneralQueryMode;
function processWar(string $warSeed, General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity)
{
@@ -29,23 +31,39 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
}
$gameStor = KVStorage::getStorage($db, 'game_env');
[$startYear, $year, $month, $cityRate, $joinMode] = $gameStor->getValuesAsArray(['startyear', 'year', 'month', 'city_rate', 'join_mode']);
[$startYear, $year, $month, $joinMode] = $gameStor->getValuesAsArray(['startyear', 'year', 'month', 'join_mode']);
$attacker = new WarUnitGeneral($rng, $attackerGeneral,$rawAttackerNation, true);
$city = new WarUnitCity($rng, $rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
$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'));
$defenderList = General::createGeneralObjListFromDB($defenderIDList, null, 2);
$defenderCityGeneralIDList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i AND nation!=0', $city->getVar('nation'), $city->getVar('city'));
$defenderCityGeneralList = General::createObjListFromDB($defenderCityGeneralIDList, null);
usort($defenderList, function (General $lhs, General $rhs) {
return - (extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
/** @var WarUnit[] */
$defenderList = [];
foreach($defenderCityGeneralList 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->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) {
$prevDefender->applyDB($db);
}
@@ -58,24 +76,16 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
return null;
}
/** @var WarUnit */
$nextDefender = $iterDefender->current();
$nextDefender->setRawCity($rawDefenderCity);
if (extractBattleOrder($nextDefender) <= 0) {
if (extractBattleOrder($nextDefender, $attacker) <= 0) {
return null;
}
$retVal = new WarUnitGeneral(
$rng,
$nextDefender,
$rawDefenderNation,
false
);
$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);
@@ -90,7 +100,7 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
$rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice;
$rice *= getTechCost($rawDefenderNation['tech']);
$rice *= $cityRate / 100 - 0.2;
$rice *= $city->getCityTrainAtmos() / 100 - 0.2;
Util::setRound($rice);
$updateDefenderNation['rice'] = max(0, $rawDefenderNation['rice'] - $rice);
@@ -113,8 +123,8 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
'dead' => $db->sqleval('dead + %i', $totalDead * 0.6)
], 'city=%i', $rawDefenderCity['city']);
$attackerIncTech = buildNationTypeClass($rawAttackerNation['type'])->onCalcDomestic('기술', 'score', $attacker->getDead() * 0.01);
$defenderIncTech = buildNationTypeClass($rawDefenderNation['type'])->onCalcDomestic('기술', 'score', $attacker->getKilled() * 0.01);
$attackerIncTech = buildNationTypeClass($rawAttackerNation['type'])->onCalcDomestic('기술', 'score', $attacker->getDead() * 0.012);
$defenderIncTech = buildNationTypeClass($rawDefenderNation['type'])->onCalcDomestic('기술', 'score', $attacker->getKilled() * 0.009);
$attackerGenCnt = $rawAttackerNation['gennum'];
$defenderGenCnt = $rawDefenderNation['gennum'];
@@ -175,13 +185,21 @@ function processWar(string $warSeed, General $attackerGeneral, array $rawAttacke
'startyear' => $startYear,
'year' => $year,
'month' => $month,
'city_rate' => $cityRate,
'join_mode' => $joinMode,
], $attacker->getGeneral(), $city->getRaw());
], $attacker->getGeneral(), $city->getRaw(), $defenderCityGeneralList);
}
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) {
return 0;
}
@@ -212,7 +230,6 @@ function processWar_NG(
WarUnitGeneral $attacker,
callable $getNextDefender,
WarUnitCity $city,
int $relYear
): bool {
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
@@ -225,6 +242,7 @@ function processWar_NG(
$attackerNationUpdate = [];
$defenderNationUpdate = [];
/** @var WarUnit */
$defender = ($getNextDefender)(null, true);
$conquerCity = false;
@@ -240,6 +258,7 @@ function processWar_NG(
$logWritten = false;
if ($defender === null) {
$defender = $city;
$defender->setSiege();
if ($city->getNationVar('rice') <= 0 && $city->getVar('supply')) {
//병량 패퇴
@@ -406,21 +425,28 @@ function processWar_NG(
$attacker->logBattleResult();
$defender->logBattleResult();
$attacker->addWin();
$defender->addLose();
if (!($defender instanceof WarUnitCity) || $defender->isSiege()){
$attacker->addWin();
$defender->addLose();
$attacker->tryWound();
$defender->tryWound();
$attacker->tryWound();
$defender->tryWound();
if ($defender === $city) {
$attacker->addLevelExp(1000);
$conquerCity = true;
break;
if ($defender === $city) {
$attacker->addLevelExp(1000);
$conquerCity = true;
break;
}
}
$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} 패퇴했습니다.");
$attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.", ActionLogger::PLAIN);
$defender->getLogger()->pushGeneralActionLog("군량 부족으로 패퇴합니다.", ActionLogger::PLAIN);
@@ -455,12 +481,18 @@ function processWar_NG(
$attacker->finishBattle();
$defender->finishBattle();
if ($defender instanceof WarUnitCity) {
$newConflict = $defender->addConflict();
if($city->getDead() || $defender instanceof WarUnitCity){
if($city !== $defender){
$city->setOppose($attacker);
$city->setSiege();
$city->finishBattle();
}
$newConflict = $city->addConflict();
if ($newConflict) {
$nationName = $attacker->getNationVar('name');
$josaYi = JosaUtil::pick($nationName, '이');
$logger->pushGlobalHistoryLog("<M><b>【분쟁】</b></><D><b>{$nationName}</b></>{$josaYi} <G><b>{$defender->getName()}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다.");
$logger->pushGlobalHistoryLog("<M><b>【분쟁】</b></><D><b>{$nationName}</b></>{$josaYi} <G><b>{$city->getName()}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다.");
}
}
@@ -497,8 +529,9 @@ function getConquerNation($city): int
return Util::array_first_key($conflict);
}
function ConquerCity(array $admin, General $general, array $city)
function ConquerCity(array $admin, General $general, array $city, array $defenderCityGeneralList)
{
/** @var General[] $defenderCityGeneralList */
$db = DB::db();
$year = $admin['year'];
@@ -550,23 +583,25 @@ function ConquerCity(array $admin, General $general, array $city)
$gameStor = KVStorage::getStorage($db, 'game_env');
// 이벤트 핸들러 동작
$e_env = null;
foreach (DB::db()->query('SELECT * FROM event WHERE target = "OCCUPY_CITY" ORDER BY `priority` DESC, `id` ASC') as $rawEvent) {
if ($e_env === null) {
$e_env = $gameStor->getAll(false);
}
$eventID = $rawEvent['id'];
$cond = Json::decode($rawEvent['condition']);
$action = Json::decode($rawEvent['action']);
$event = new Event\EventHandler($cond, $action);
$e_env['currentEventID'] = $eventID;
$event->tryRunEvent($e_env);
if(TurnExecutionHelper::runEventHandler($db, $gameStor, EventTarget::OccupyCity)){
$gameStor->cacheAll();
}
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'ConquerCity',
$year,
$month,
$attackerNationID,
$attackerID,
$cityID
)));
foreach($defenderCityGeneralList as $defenderCityGeneral){
$defenderCityGeneral->onArbitraryAction($defenderCityGeneral, $rng, 'ConquerCity', null, [
'attacker' => $general
]);
$defenderCityGeneral->applyDB($db);
}
if ($e_env !== null) {
$gameStor->resetCache();
}
// 국가 멸망시
if ($defenderNationID && $db->queryFirstField('SELECT count(city) FROM city WHERE nation = %i', $defenderNationID) === 1) {
@@ -577,10 +612,10 @@ function ConquerCity(array $admin, General $general, array $city)
$lord = new General($db->queryFirstRow(
'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()[0]),
$defenderNationID,
12
), null, $city, $loseNation, $year, $month, false);
), null, null, $city, $loseNation, $year, $month);
$josaUl = JosaUtil::pick($defenderNationName, '을');
$attackerLogger->pushNationalHistoryLog("<D><b>{$defenderNationName}</b></>{$josaUl} 정복");
@@ -662,27 +697,11 @@ function ConquerCity(array $admin, General $general, array $city)
}
// 이벤트 핸들러 동작
$e_env = null;
foreach (DB::db()->query('SELECT * FROM event WHERE target = "DESTROY_NATION" ORDER BY `priority` DESC, `id` ASC') as $rawEvent) {
if ($e_env === null) {
$e_env = $gameStor->getAll(false);
}
$eventID = $rawEvent['id'];
$cond = Json::decode($rawEvent['condition']);
$action = Json::decode($rawEvent['action']);
$event = new Event\EventHandler($cond, $action);
$e_env['currentEventID'] = $eventID;
$event->tryRunEvent($e_env);
}
if ($e_env !== null) {
$gameStor->resetCache();
}
TurnExecutionHelper::runEventHandler($db, $gameStor, EventTarget::DestroyNation);
// 멸망이 아니면
} else {
// 태수,군사,종사 일반으로...
// 태수,군사,종사 일반으로...
$db->update('general', [
'officer_level' => 1,
'officer_city' => 0,
@@ -693,11 +712,12 @@ function ConquerCity(array $admin, General $general, array $city)
$minCity = findNextCapital($cityID, $defenderNationID);
$minCityName = CityConst::byID($minCity)->name;
$josaRo = JosaUtil::pick($minCityName, '로');
$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(
'SELECT no FROM general WHERE nation=%i AND officer_level>=5',
+2
View File
@@ -11,6 +11,7 @@ include "func.php";
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>최근 지도</title>
@@ -27,6 +28,7 @@ include "func.php";
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/map.css') ?>
<?= WebUtil::printDist('ts', ['common', 'recent_map'], true) ?>
<?= WebUtil::printDist('vue', [], true) ?>
<style>
html {
width: 700px;
+3 -2
View File
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use sammo\AuctionBuyRice;
use sammo\AuctionUniqueItem;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\General;
@@ -32,13 +33,13 @@ class BidBuyRiceAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$auctionID = $this->args['auctionID'];
$amount = $this->args['amount'];
$generalID = $session->generalID;
$general = General::createGeneralObjFromDB($generalID);
$general = General::createObjFromDB($generalID);
$auction = new AuctionBuyRice($auctionID, $general);
$result = $auction->bid($amount, true);
+3 -2
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Auction;
use sammo\Session;
use DateTimeInterface;
use sammo\AuctionSellRice;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\General;
@@ -31,13 +32,13 @@ class BidSellRiceAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$auctionID = $this->args['auctionID'];
$amount = $this->args['amount'];
$generalID = $session->generalID;
$general = General::createGeneralObjFromDB($generalID);
$general = General::createObjFromDB($generalID);
$auction = new AuctionSellRice($auctionID, $general);
$result = $auction->bid($amount, true);
+4 -3
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Auction;
use sammo\Session;
use DateTimeInterface;
use sammo\AuctionUniqueItem;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\GameConst;
use sammo\General;
@@ -33,14 +34,14 @@ class BidUniqueAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$auctionID = $this->args['auctionID'];
$amount = $this->args['amount'];
$tryExtendCloseDate = $this->arg['extendCloseDate'] ?? false;
$tryExtendCloseDate = $this->args['extendCloseDate'] ?? false;
$generalID = $session->generalID;
$general = General::createGeneralObjFromDB($generalID);
$general = General::createObjFromDB($generalID);
$auction = new AuctionUniqueItem($auctionID, $general);
$result = $auction->bid($amount, $tryExtendCloseDate);
@@ -8,6 +8,7 @@ use sammo\AuctionSellRice;
use sammo\DB;
use sammo\DTO\AuctionBidItem;
use sammo\DTO\AuctionInfo;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\AuctionType;
use sammo\Validator;
use sammo\General;
@@ -29,7 +30,7 @@ class GetActiveResourceAuctionList extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
@@ -8,7 +8,9 @@ use sammo\AuctionUniqueItem;
use sammo\DB;
use sammo\DTO\AuctionBidItem;
use sammo\DTO\AuctionInfo;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\AuctionType;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\InheritanceKey;
use sammo\InheritancePointManager;
use sammo\TimeUtil;
@@ -37,7 +39,7 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
@@ -75,7 +77,7 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI
$inheritMgr = InheritancePointManager::getInstance();
//preveious라서 column을 최대한 비울 수 있다.
$remainPoint = $inheritMgr->getInheritancePoint(
General::createGeneralObjFromDB($generalID, ['owner'], 0),
General::createObjFromDB($generalID),
InheritanceKey::previous
);
@@ -8,6 +8,7 @@ use sammo\AuctionUniqueItem;
use sammo\DB;
use sammo\DTO\AuctionBidItem;
use sammo\DTO\AuctionInfo;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\AuctionType;
use sammo\TimeUtil;
use sammo\Util;
@@ -24,7 +25,7 @@ class GetUniqueItemAuctionList extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
+3 -2
View File
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use sammo\AuctionBuyRice;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\GameConst;
use sammo\General;
@@ -52,7 +53,7 @@ class OpenBuyRiceAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
/** @var int */
$amount = $this->args['amount'];
@@ -65,7 +66,7 @@ class OpenBuyRiceAuction extends \sammo\BaseAPI
$finishBidAmount = $this->args['finishBidAmount'];
$generalID = $session->generalID;
$general = General::createGeneralObjFromDB($generalID);
$general = General::createObjFromDB($generalID);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');

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