Compare commits

...
722 Commits
Author SHA1 Message Date
sars 74f914488b 빙의 금지 장수 포함 2024-12-05 00:04:10 -08:00
sars a8d219afec iconPath 재설정, 100에서 29로 숫자 조절 2024-12-04 23:26:54 -08:00
sars 4b4a7ffdf0 롤 시나리오 1.0으로 업데이트, 비급 and/or 파죽지세도 추가 2024-12-04 23:04:36 -08:00
sars 05000ae954 리그오브레전드 베타 아이콘 추가 2024-12-02 19:21:45 -08:00
Hide_D 85bf53f317 챔피언들과 미니언들 시작날짜 조절 (#260)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/260
2024-11-27 17:42:28 +09:00
sars d65407079e 챔피언들과 미니언들 시작날짜 조절 v2 2024-11-27 00:11:52 -08:00
sars a8c9946aa9 챔피언들과 미니언들 시작날짜 조절 2024-11-26 23:59:35 -08:00
Hide_D 1e5b2de913 LoL 시나리오 생년월일 (#257)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/257
2024-11-27 16:26:34 +09:00
Hide_D 747ab3d563 LoL 시나리오 생년월일 2024-11-27 16:26:08 +09:00
sars 82ffbba661 수식을 수치로 수정해서 다시 변환시도 2024-11-26 23:18:01 -08:00
sars 3f08876079 리그오브레전드 시나리오 추가 2024-11-26 23:09:37 -08:00
Hide_D 5622839ffa feat: 설문 게시자 표시 2024-09-28 13:09:51 +00:00
Hide_D 4b3ab5e31c feat: 설문 등록 시 등록자 유저명 저장 2024-09-28 13:04:29 +00:00
Hide_D f774a28e2a fix: 로그인 시 세션에 저장되는 username을 id가 아니라 name값으로 변경 2024-09-28 13:03:00 +00:00
Hide_D 61bdb8da01 fix: 부대 이름 변경 오작동 2024-09-23 13:43:35 +00:00
Hide_D c117ada117 fix: event 커맨드 수정
- 탑승즉시이동: 불필요한 추가 조사 제거
- 발령즉시집합: 발령자가 탑승중인 경우 변수값 변경
  - 장수 커맨드 실행 시 cityID에 따라 다시 받아오므로 해당 변경으로 충분
2024-09-23 13:35:28 +00:00
Hide_D 1f0d0f992d game: 부대탈퇴지시 ui 2024-09-18 16:30:01 +00:00
Hide_D 6445b77b90 game: 부대탑승후 이동 이벤트시 로그 기록 2024-09-18 16:17:24 +00:00
Hide_D 6d935733e6 game: 충차 도구 치안치 하향 2024-09-18 16:09:02 +00:00
Hide_D cfd0a2d26f game: 충차 도구 추가 2024-09-18 16:08:37 +00:00
Hide_D 749e8f673b fix: StaticEventHandler 버그 수정 2024-09-18 16:08:25 +00:00
Hide_D 4812f324e0 fix: StaticEventHandler 버그 수정 2024-09-18 16:02:41 +00:00
Hide_D 085f34b307 feat: 부대탈퇴지시 2024-09-18 15:22:27 +00:00
Hide_D 622ce7b780 game: 축지 시나리오 벌점 제한 2배 2024-09-18 15:11:18 +00:00
Hide_D 34b1fc9c5e feat: 벌점 제한 계수를 GameConst로 이동 2024-09-18 15:10:34 +00:00
Hide_D 9cc27c40aa game: 축지 시나리오 수비 설정 제한 완화 2024-09-18 15:08:37 +00:00
Hide_D eece1cbae5 feat: 수비 설정 제한을 GameConst로 이동 2024-09-18 15:08:21 +00:00
Hide_D 7e6770b5e7 game: 축지 시나리오 유닛세트 2024-09-18 15:02:38 +00:00
Hide_D a0c032c2c6 game: 축지 이벤트 작업 2024-09-18 14:54:56 +00:00
Hide_D 3d12de3838 refac: API/Troop 의 $me를 GeneralLite로 변경
- StaticEventHandler 처리도 추가
2024-09-18 14:54:40 +00:00
Hide_D 477b77b59f feat: StaticEventHandler 처리기 추가
- 커맨드 종료 시점에 호출
  - pre, post 각각이 필요한지는 논의 필요
  - 일단 용도에 따라 pre, post 둘중에 하나만 처리
- eventType으로는 full qualified class name 사용
  - 꼭 그럴필요는 없지만, 커맨드에 한해서는 이렇게
2024-09-18 14:54:11 +00:00
Hide_D 04a7a34fcc 부대 이동 관련 초기 코드 2024-09-17 00:48:54 +09:00
Hide_D 86f1805160 fix: 병가 인구 상승률 버그 수정 (#255)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/255
2024-07-30 14:57:43 +09:00
jyp9 d573e9f98a fix: 병가 인구 상승률 버그 수정
fix: 병가 인구 상승률 버그 수정
2024-07-30 14:55:40 +09:00
Hide_D 3ad16d96be game: 긴급천도시 모든 장수에게 알림,
- 수뇌에게는 집합 메시지도 남김
2024-07-16 13:09:43 +09:00
Hide_D d8870caf29 feat: 포인트 초기화 추가
- 급하니까 일단 땜빵
2024-07-10 18:11:10 +00:00
Hide_D 7c9d5d34f6 feat: 스탯 초기화용 API 준비 2024-07-10 17:20:38 +00:00
Hide_D 5268ce9b71 game: 훈련, 사기진작 시 병력이 낮을 때도 숙련 상승량 조정 2024-07-10 17:00:35 +00:00
Hide_D e395c98a6c fix: 도시 주둔 장수 중 해당 국가 소속만 계략 확률 감소에 영향을 주도록 수정 (#254)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/254
2024-07-08 17:01:17 +09:00
Hide_D d5897e2a49 fix: 건국 유니크 100% 수정 2024-06-22 15:42:58 +00:00
Hide_D c82003f982 game: 건국시 확정 유니크, 유산 포인트 250점 2024-06-22 15:41:43 +00:00
Hide_D 5447274aa8 game: 사령턴 입력, 인사부 처리 시 삭턴 변경 2024-06-22 15:28:39 +00:00
Hide_D 688162ffbf fix: 이벤트 클래식은 907이 아니라 908이었어야함 2024-06-20 12:31:49 +00:00
Hide_D 220d1d821d fix: 삼황내문 로직 누락 수정 2024-06-19 13:23:07 +09:00
Hide_D 2b16c3c1a9 fix: 삼황내문을 새 저지 로직에 맞게 변경 2024-06-19 13:22:20 +09:00
Hide_D d731acdaef Revert "fix: 삼황내문을 새 저지 로직에 맞게 수정"
This reverts commit 3511b159a8.
2024-06-19 13:19:30 +09:00
Hide_D 3511b159a8 fix: 삼황내문을 새 저지 로직에 맞게 수정 2024-06-19 13:18:15 +09:00
Hide_D 28cea4ee09 fix: 메시지 수정 2024-06-08 18:55:48 +00:00
Hide_D 8e7227c29d fix: DummyGeneral에 penaltyList 2024-06-08 18:52:47 +00:00
Hide_D f0cc22d9d8 fix: NoChief 처리 부실 2024-06-08 18:48:46 +00:00
Hide_D b6f19fa38b feat: 유산포인트로 장수 소유자 확인 2024-06-08 18:42:39 +00:00
Hide_D 86305087f7 Revert "장수목록에서 장수명에 마우스를 올리면 본닉 공개"
This reverts commit a3d7ef30dd.
2024-06-08 17:52:13 +00:00
Hide_D 7b6f64db61 fix: 유저장이 수뇌 금지 장수밖에 없을때 NPC 임명 동작 2024-06-08 17:47:35 +00:00
Hide_D 06f086bcf0 fix: penalty 오타 2024-06-08 17:37:43 +00:00
Hide_D 606c1664f2 feat: 내정보에 징계목록 출력 2024-06-08 17:37:33 +00:00
Hide_D 0c07060f4d feat: 메시지 전송 페널티 2024-06-08 17:22:10 +00:00
Hide_D 8bd0cc1c64 feat: 건국 금지, 지정 임관 금지 패널티 2024-06-08 17:21:55 +00:00
Hide_D f12262b946 feat: 건국 불가 페널티 2024-06-08 16:16:52 +00:00
Hide_D 9415d79a3a feat: Constraint 시스템에 NoPaneltyKey 추가 2024-06-08 16:15:19 +00:00
Hide_D ad223a9c75 feat: NPC 임명로직에 NoChief, NoAmbassador 반영 2024-06-08 16:06:22 +00:00
Hide_D 8737b19e79 fix: 이미 수뇌인 장수는 NPC에게 외교권을 못받는 버그 수정 2024-06-08 15:58:52 +00:00
Hide_D 552d73430c feat: 유저장의 수뇌 임명 불가 penalty 2024-06-08 15:55:26 +00:00
Hide_D fba5fbdb6b feat: PenaltyKey::NoChiefTurnInput 2024-06-08 15:48:01 +00:00
Hide_D 3da11bf21c feat: 내 정보 설정 저장지 페널티 갱신 2024-06-08 15:41:27 +00:00
Hide_D c83f9a0465 game: 휴전 -> 종전 2024-06-08 14:43:40 +00:00
Hide_D 9f67ae1f4e feat: General::penaltyList 2024-06-08 14:38:31 +00:00
Hide_D 383431b79f feat: PenaltyKey enum 2024-06-08 14:06:12 +00:00
Hide_D d5c0d16758 game: 저지 작동 방식 변경
- 최대 페이즈를 1 깎는 형태로 변경
2024-06-08 13:24:32 +00:00
devsamanddevsam 87294d5477 fix: 도시 주둔 장수 중 해당 국가 소속만 계략 확률 감소에 영향을 주도록 수정 2024-06-01 07:00:35 +09:00
Hide_D c45758b054 game: 이벤트 클래식 유니크 최대 획득 확률 계수 수정 2024-05-22 17:45:45 +00:00
Hide_D a84f07f3ad game: 이벤트 클래식 시나리오 2024-05-22 17:43:29 +00:00
Hide_D 3c6ed3441b fix: MeekroDB 최신버전에서는 $db->get()으로 raw 호출을 먼저 시작해선 안됨 2024-05-22 17:00:27 +00:00
Hide_D 68cd61d86e fix: file_cache 문제 추가 수정 2024-05-22 16:47:20 +00:00
Hide_D 3470817e9e Nette FileStorage 요구 주소 문제 2024-05-22 16:45:29 +00:00
sars a3d7ef30dd 장수목록에서 장수명에 마우스를 올리면 본닉 공개 2024-05-20 19:03:51 -07:00
Hide_D db09e8da89 composer upgrade 2024-05-17 18:26:08 +00:00
Hide_D 37fa5321cc 초기 설치 코드 정돈, meekrodb 반영 2024-05-17 18:18:37 +00:00
Hide_D 63edb03193 APIHelper에 MeekroDBExceptionr에러시 logError 2024-05-17 18:16:54 +00:00
Hide_D 8d02102024 dep 2024-05-17 18:14:32 +00:00
Hide_D 75a13094e0 game: 해산시 군주외 장수는 즉시 임관 가능 2024-03-16 18:18:35 +00:00
Hide_D 7a4c70ada2 game: 강서유서 소설 월드 2024-03-16 18:07:59 +00:00
Hide_D 65c84a29e1 fix: 방랑군이동시 현재 소재 위치 확인 2024-03-16 18:07:42 +00:00
Hide_D eea34dadad fix: 이민족 수도 이동 2024-03-05 16:44:27 +00:00
Hide_D f1e6ac7b89 fix: 이민족 도시 이동 규칙 재작성
- 무한루프일 수 있으므로 그냥 SQL에 NOT IN을 넣자..
2024-02-29 10:35:32 +09:00
Hide_D 7b24f66f93 fix: 버그 수정 2024-02-29 10:28:10 +09:00
Hide_D b2b2934ce9 refac: 전체 penalty는 expire와 value
- 게임 개시시 expire가 되지 않은 것을 기준 value만 전달
- 즉, 페널티는 깃수 단위 적용
2024-02-29 10:27:04 +09:00
Hide_D 6ed3e673df game: 내정이라는 용어의 중의성 해소를 위해, 국가 성향의 내정이란 용어를 농상으로 바꾸고, 물자조달 커맨드를 내정의 하위 분류에서 국가로 이동 (#249)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/249
2024-02-29 10:18:00 +09:00
Hide_D aa7dcab1fd fix: 이민족 발동 시 수도가 이성이라 수도를 옮겼는데 다시 이성이 되는 경우 해결 (#250)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/250
2024-02-29 10:17:52 +09:00
devsamanddevsam e2e578e485 game: 내정이라는 용어의 중의성 해소를 위해, 국가 성향의 내정이란 용어를 농상으로 바꾸고, 물자조달 커맨드를 내정의 하위 분류에서 국가로 이동 2024-02-29 08:09:23 +09:00
devsamanddevsam 6cebc903c9 fix: typo 2024-02-29 08:02:11 +09:00
devsamanddevsam c0190959e3 fix: 이민족 발동 시 수도가 이성이라 수도를 옮겼는데 다시 이성이 되는 경우 해결 2024-02-29 08:01:02 +09:00
Hide_D bb26366769 fix: 이민족 발동 시 이성이 수도인 경우 문제 해결 2024-02-26 16:05:37 +00:00
Hide_D 71849a457b game: 종횡가의 전략 디메리트 감소
- 전략 쿨타임 2배 -> 4/3배
2024-02-26 16:01:16 +00:00
Hide_D 7c1a8d96a2 fix: 정규턴에 어긋나는 개인턴, 사령턴을 보정
- 조회시에만 사용
2024-02-26 15:58:41 +00:00
Hide_D cebd152daf fix: 경매장 소수점 제거 2024-02-26 15:43:07 +00:00
Hide_D 2ca03389d2 fix: 유니크 경매 항목 변경시 금액이 자동 조절되도록 수정
- 굳이 기존 값을 남길 이유가 없어보임
2024-02-24 15:14:24 +00:00
Hide_D cacf0981ce game: 턴 시간과 도시 지정을 같이 가능하도록 변경 2024-02-24 12:05:49 +00:00
Hide_D bcf5b5cb7d game: 턴 지정 단위를 1/30에서 1/60으로 변경 2024-02-24 11:46:32 +00:00
Hide_D 66b2f1a8f2 game: NPC는 건국 한턴 기다림 2024-02-24 11:45:08 +00:00
Hide_D 40ecca5440 game, feat: 커맨드마다 다른 랜덤값으로 유니크 시도
- 사전 거병 후 개인 턴일 때, 유니크 중복이 발생하는 경우가 있었음
2024-02-24 11:28:38 +00:00
Hide_D a96c2312d0 game, feat: 턴 시간 지정 방식을 30단계 중 선택하도록 변경
- 1분서버인 경우 120초 단위로
- 유산포인트 3000 -> 2500
2024-02-24 11:21:04 +00:00
Hide_D faff3f4e6a JSON -> Json
- 대체 왜 어떤 파일에는 에러가 나지 않았는가
2024-02-20 18:45:40 +09:00
Hide_D 83abf44380 feat: 유저의 제재 목록을 장수 생성/빙의시 가져옴 2024-02-18 03:24:21 +00:00
Hide_D e83960d67f fix: 사전거병시 삭턴 정상 반영 2024-02-18 03:10:42 +00:00
Hide_D c6b2e64c05 penalty에 sendPrivateMsgDelay추가 2024-02-18 03:08:21 +00:00
Hide_D 029f719112 fix: 스탯 계산 시에 캐시 사용하는 부분 수정 시도 (#241)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/241
2024-02-17 00:01:49 +09:00
Hide_D 46f460c8ad Merge branch 'devel' into stat_cache_fix 2024-02-17 00:01:40 +09:00
Hide_D af4401d9bb fix: 사전거병 후 군주가 사라지는 경우에 대한 수정 (#247)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/247
2024-02-17 00:01:34 +09:00
devsamanddevsam 2f00aee947 아주 약간 효율적으로 수정 2024-01-26 22:17:06 +09:00
devsamanddevsam dd2b032fa3 리뷰 내용 반영 2024-01-26 22:13:44 +09:00
Hide_D 1b858ae36c fix: onCalcOpposeStat이 제대로 전파되지 않았음 2023-12-30 04:15:33 +00:00
devsamanddevsam 69f4d8e2c7 fix: 사전거병 후 군주가 사라지는 경우에 대한 수정 2023-12-29 12:07:59 +09:00
Hide_D f24aea0120 fix: 수정된 턴 시간 변경 로직에서 바뀌기 이전 턴을 시드로 계속 사용하는 문제 수정 (#246)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/246
Reviewed-by: Hide_D <hided62@gmail.com>
2023-12-27 17:42:48 +09:00
Jinhyun Kim f6dc7f49e2 fix: 수정된 턴 시간 변경 로직에서 바뀌기 이전 턴을 시드로 계속 사용하는 문제 수정 2023-12-27 17:25:51 +09:00
Hide_D c1f105226f refac: 기존 commandButton.php 삭제
- 이젠 MainControlBar로 대체됨
2023-12-25 08:28:36 +00:00
Hide_D cecab2b0cf feat: 이호경식 발동시 '어느 국가'인지 바로 표기 2023-12-25 08:07:57 +00:00
Hide_D 39f4e89b03 feat: HasRouteWithEnemy에서 "교전 중인 국가가 아닙니다" 추가
- 경로에 도달할 방법이 없는 것은 맞으나..
- 교전중이 아니라는 것에 의미가 있음
2023-12-25 08:05:34 +00:00
Hide_D 83f595a27a feat: 종전시 세력 정보란에 문구 남김 2023-12-25 07:59:57 +00:00
Hide_D b0db11544d fix: 인사부 연동 스크립트 오타 수정 2023-12-25 07:56:27 +00:00
Hide_D 8e3551cb11 feat: 턴 시간 변경을 직관적인 동작으로 재 설계
- '다다음턴' 부터 시간을 00:00 ~ 59:59까지 랜덤하게
2023-12-25 07:51:54 +00:00
Hide_D 61d99a3043 초기 3년 이전에도 하야 가능
- 기존엔 1인국의 문제가 있었으나, 이미 NPC국이 자리를 채웠다.
2023-12-25 07:30:25 +00:00
Hide_D fe80deff0c 【가상모드27-e】 아시아 명장전(비급+파죽지세) (#244)
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/244
2023-11-21 00:12:38 +09:00
포스트모더니즘 536c00f5a8 【가상모드27-e】 아시아 명장전(비급+파죽지세) 2023-11-21 00:04:20 +09:00
포스트모더니즘 66ed8635dd 【가상모드14-b】 걸그룹대전(비급) 시나리오 추가 2023-11-20 23:49:45 +09:00
포스트모더니즘 311c485cec fix: 불가침 제의를 같은 국가로 지정할 수 있는 버그 수정 2023-10-30 12:23:16 +09:00
포스트모더니즘andHide_D 5b5cf4e6d3 misc: 허보 대상 도시 선택 시에 선포 중인 경우 추가 2023-10-30 09:21:47 +09:00
포스트모더니즘 c5ed2d47fc fix: 스탯 계산 시에 캐시 사용하는 부분 수정 시도 2023-10-29 09:05:29 +09:00
포스트모더니즘 428ec0d0ed misc: 유니크 경매 취소 시에 경매 경매가 취소되었다고 표시되는 문제 수정 2023-10-29 08:37:36 +09:00
Jinhyun Kim 96c5f987d6 misc: 등용장 수락 시에도 국가 이름 볼드 처리 2023-10-14 07:57:27 +09:00
Hide_D f0ae28b087 fix: 이전 커밋에서 ' 하나를 "로 변경 2023-09-15 12:54:31 +09:00
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
Hide_D dca341f35e fix: 연산단위 최소값 지정 2022-06-15 23:11:07 +09:00
Hide_D d38ddcd79e fix: 피장파장에서 모든 국가에(불가)가 나타나는 버그 2022-06-15 22:34:32 +09:00
Hide_D 03675349d8 fix: 사기진작 커맨드가 금소모를 하지 않음 2022-06-15 00:35:40 +09:00
Hide_D 72768ba7b5 fix: 경매 로그 마저 수정 2022-06-14 22:31:01 +09:00
Hide_D a5477db6b6 fix: 거래 완료시 메시지가 반대로 뜨는 버그 수정 2022-06-14 22:19:23 +09:00
Hide_D c146e8587b feat: 명장일람에 진행중인 유니크 경매 표시 2022-06-12 17:52:02 +09:00
Hide_D 24b65b0395 fix: 금쌀 경매장에 최근 로그 없음 2022-06-12 01:50:33 +09:00
Hide_D 2f42691d2b fix: 연감에 전투 시드가 겉으로 드러남 2022-06-11 15:09:35 +09:00
Hide_D ea619bd693 misc: 인사부에서 추방을 가장 아래로 2022-06-11 14:39:57 +09:00
Hide_D 35a56e74bb refac: 금쌀 경매장 UI 2022-06-11 03:53:30 +09:00
Hide_D 6fb2358161 refac: 유니크 경매 UI 수정 2022-06-10 02:07:05 +09:00
Hide_D a039fb871b fix: CreateManyNPC에서 모든 m장 사망년도가 같은 버그 수정 2022-06-10 00:49:47 +09:00
Hide_D a19da6cda5 fix: 경매장 갱신 버튼 2022-06-10 00:43:47 +09:00
Hide_D e5ba980865 fix: 종료된 유니크 경매 입찰시 버그 2022-06-10 00:38:34 +09:00
Hide_D f95ee8fab8 fix: 경매에서 이미 소지 수가 찬 유니크 획득 가능한 문제 수정 2022-06-09 22:28:51 +09:00
Hide_D 120706ef3f misc: 경매장 진입로를 금/쌀, 유니크로 2원화 2022-06-09 16:16:58 +09:00
Hide_D 58da20f276 fix: 동일 부위 유니크 소유시, '1턴' 연장하도록 수정 2022-06-09 15:49:13 +09:00
Hide_D 64af68e2d6 fix: 유니크 경매 시 종류 제한 계산 버그 2022-06-09 02:03:38 +09:00
Hide_D 76a8740644 fix: 유니크 경매시 10포인트 더 높아야 함 2022-06-09 01:53:19 +09:00
Hide_D 0863fafec0 fix: 경매가 시작후 3개월이 아니라 4개월로 설정됨 2022-06-09 01:49:22 +09:00
Hide_D 42579810a2 game: NPC의 이후 임관 확률을 낮춤 2022-06-09 01:30:08 +09:00
Hide_D 47e6b91b82 game: 시나리오 초기 생성 m장의 수명 증가 2022-06-09 01:25:41 +09:00
Hide_D dd38344319 feat,refac: 경매장 재설계, 유니크 경매장 구현 (#221)
- 경매장을 모든 입찰 기록이 남는 새로운 경매장 로직으로 변경
  - ng_auction, ng_auction_bid
    - DTO 사용
  - 상회입찰 시 개인메시지로 알림
- 기존의 '배경에서 조용히 이루어지는' 유니크 입찰을 공개된 유니크 경매장으로 변경
  - 종료 기간 명시
    - 종료 기간에 가까워질때 입찰하면 자동 연장
    - 최대 연장기간 있음
  - 유니크 제한인 경우 24턴 연장
  - 중원정세에서 '보물수배'로 알림

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/221
2022-06-09 01:21:55 +09:00
Hide_D 7964aa5f6b refac: phan warning 제거, nationStor변수 위치 2022-06-09 01:18:20 +09:00
Hide_D 85d372ecec refac: KakaoUtil 난수 random 타입 변경 2022-06-09 01:18:11 +09:00
Hide_D 6a2b27b875 fix: DummyGeneral에서 logger가 제대로 지정되었을 경우 대비 2022-06-09 01:18:06 +09:00
Hide_D 3b8a82fa42 game: 신규시나리오 누락 이벤트 추가 2022-06-07 01:56:21 +09:00
Hide_D 551e17b37b game: 삼모 시네마틱 유니버스 시나리오 2022-06-07 01:52:33 +09:00
Hide_D acccb74b4e feat: DTO에 toArrayExcept 추가 2022-06-04 21:29:47 +09:00
Hide_D 39be8fa4b8 fix: 감찰부 하단 버튼이 '돌아가기'인 버그 수정(임시) 2022-06-04 13:25:35 +09:00
Hide_D fc0c183ca3 game: 아이콘 크기를 30kb에서 50kb로 증량 2022-06-03 18:39:57 +09:00
Hide_D 329a461721 game: 방랑 커맨드 비활성화 2022-05-31 14:58:01 +09:00
Hide_D 35b178fe3c refac: DTO 구조 변경
- Converter - Constructor 관련 경고 수정
- JsonString 관련 의존성 제거, jsonFlag 지정
- DateTimeConveter에서 time format 지정
2022-05-29 00:44:28 +09:00
Hide_D 7464629597 feat: DTO에 Ignore 추가 2022-05-28 16:12:54 +09:00
Hide_D cb3982e57c feat: DTO에 DefaultValue, DefaultValueGenerator 추가 2022-05-28 15:53:06 +09:00
Hide_D 08eae297fd feat: DTO Convert 인자 버그 수정, DateTimeConverter 확장
- DateTimeConverter에 목표 Timezone 설정
2022-05-28 02:50:21 +09:00
Hide_D c46128ed3e feat: DTO에 DateTimeConveter 추가 2022-05-28 02:15:17 +09:00
Hide_D 78a55fb87a refac: 변경한 DTO에 따라 코드 수정
- Spatie/DataTransferObject 대비
  - MapFrom,MapTo -> RawName
  - Strict -> 항상
     - 심지어 raw type도 더 까다롭게
  - array에 MapConverter 적용
  - NullIsUndefined 적용
  - 빈 nullable arg자리에 null 강제 지정
- Vue3에 v-model.number 지정
  - input type="number" 기준
2022-05-22 22:39:28 +09:00
Hide_D 43a5162a15 feat: 직접 작성한 DTO 2022-05-22 16:53:56 +09:00
Hide_D cb5cb68bf4 Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2022-05-19 02:49:25 +09:00
Hide_D b79a655d56 misc: git ignore 일부 수정 2022-05-19 02:48:52 +09:00
Hide_D 5b19c24f84 fix: 필살 비급 패치 누락 2022-05-18 17:28:38 +09:00
Hide_D e3716bda56 game: 입관했던 국가 재임관 가능 2022-05-18 01:41:37 +09:00
Hide_D b710a26b3e fix: 공백지에 건국이 완료된 경우 장수 생성이 되지 않는 버그 수정 2022-05-18 01:28:00 +09:00
Hide_D e5507e1e61 fix: 리셋 시 설문조사 목록을 초기화하지 않는 버그 수정 2022-05-18 01:00:18 +09:00
Hide_D 85f3d0b500 fix: 내부 이벤트 중 deterministic seed를 사용하지 않는 부분 수정 2022-05-18 00:55:43 +09:00
Hide_D 27811f4891 fix: nextBool 대신 nextFloat1 적은 부분 수정 2022-05-18 00:53:05 +09:00
Hide_D b22987f21b fix: 진행 중 $rng 호출 관련 버그 수정 2022-05-17 23:28:31 +09:00
Hide_D 8665838472 feat: RandUtil nextBool false 엔트로피 절약 2022-05-17 23:10:52 +09:00
Hide_D da3fb2c094 feat: nextBool에서 0.5인 경우 엔트로피 절약 2022-05-17 23:08:03 +09:00
Hide_D 485d696e85 fix: ts/util/simpleSerialize continue 누락 2022-05-17 23:03:25 +09:00
Hide_D 687f2b2edf fix: 게임 진행 도중 이민족이 발동되는 경우 edge case 수정
- 국가 중 하나가 이성 하나만 보유중인 경우
2022-05-17 23:02:11 +09:00
Hide_D 296a27a409 feat,refac: 남은 난수 생성값 추가 수정
- rand, mt_rand, Query rand() 쓰는 영역
- 거래장, 토너먼트는 남김
2022-05-17 23:01:00 +09:00
Hide_D c5ceff6fb5 feat,refac: 게임 로직 내 '랜덤'을 RandUtil을 활용하여 재설정
- 기존의 랜덤 코드는 deprecated 처리
- 서버 시작 시 랜덤하게 정해진 hiddenSeed를 활용
- 랜덤 생성 단위
  - 월 실행
  - 사령턴 실행 결과
  - 커맨드 실행 결과
  - 작위 보상
  - 부대장 생성
  - 유니크 획득 시도
  - 설문 조사
  - 장수 생성
  - NPC국 생성, NPC 생성, NPC의 토너먼트 베팅
  - 전투
  - 도시 점령
  - 자율 행동 선택
  - 랜덤 턴 변경
- 거래장, 토너먼트 등 구 랜덤 코드를 이용하는 잔여 코드 있음
2022-05-17 03:46:59 +09:00
Hide_D 2cb697f3dc feat: util/simpleSerialize 추가 2022-05-17 00:07:18 +09:00
Hide_D 56fd26935d game: 도기 주기를 5년에서 2년으로, 금액 일부 상향 2022-05-16 23:47:26 +09:00
Hide_D 002b528ef8 fix: 연감 순서 조정이 1000px에도 동작 2022-05-16 23:44:32 +09:00
Hide_D 1f60f5b3a4 Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2022-05-16 23:42:54 +09:00
Hide_D cbafa4af61 feat: 연감에서 국가랭킹 위치 조절 기능 추가 2022-05-16 23:41:32 +09:00
Hide_D 19f936b6c0 feat: TopBackBar에 slot 추가 2022-05-16 23:20:11 +09:00
Hide_D 016f3c73e3 fix: 삭제된 General vote 필드 2022-05-16 15:19:34 +09:00
Hide_D 57541eca89 feat: 설문조사 시 최대 몇개까지 선택가능한지 안내 2022-05-16 02:27:34 +09:00
Hide_D b7e568fb98 fix: 설문 관련 메인 페이지 버그 2022-05-16 02:06:16 +09:00
Hide_D 438cff532b db: schema에서 더 이상 필요하지 않은 General.vote 제거 2022-05-16 02:04:09 +09:00
Hide_D 3f71490d14 fix: 메인 페이지에 최근 설문을 띄우도록 처리 2022-05-16 02:03:12 +09:00
Hide_D 2221a8c9bf fix: 설문에서 gold를 받아오지 못함 2022-05-16 01:54:46 +09:00
Hide_D 7255588bcc fix: 설문조사에서 multipleOptions 숫자 2022-05-16 01:52:39 +09:00
Hide_D c732bcddb1 misc: 설문 조사 페이지를 이전 2022-05-16 01:44:32 +09:00
Hide_D 9f363e46fc feat: 새 설문조사 모듈 UI 2022-05-16 01:41:10 +09:00
Hide_D 99242ac3d3 dep: css-color-names 추가 2022-05-16 01:03:20 +09:00
Hide_D 3d6aabda06 feat: 설문조사를 새 방식으로 구현 2022-05-15 20:55:14 +09:00
Hide_D d28a5e095a fix: 연감 페이지에서 지도가 다른 왕조 일람 역사 지도 에러 2022-05-15 18:09:18 +09:00
Hide_D 8104852abf fix: GET은 int를 arg로 받을 수 없음 2022-05-15 17:00:14 +09:00
Hide_D 459c108b13 fix: form input value가 string이 되어 number 검사에 실패 2022-05-15 16:52:23 +09:00
Hide_D d318ff7d90 dep: compose dependency 2022-05-15 02:23:27 +09:00
Hide_D 1371b84687 fix: Util::range에 yield type 지정 2022-05-14 23:48:18 +09:00
Hide_D 2cc679dcac feat: Util::generatorFromPairs 추가 2022-05-14 23:38:53 +09:00
Hide_D 04f5a1bbe1 feat: 새 설문 조사 Table 2022-05-14 23:00:01 +09:00
Hide_D 83c2fc918f misc: updateServer 시 좀 더 자세한 메시지 출력 2022-05-14 22:20:34 +09:00
Hide_D 63cfa5e298 refac: API 검증시 integer(int-like)에서 is_int로 강제 2022-05-14 22:13:51 +09:00
Hide_D 3e815691df feat: Validator에 stringArrray, int, float 추가 2022-05-14 22:03:55 +09:00
Hide_D 0fc0031574 dep: package update
- vue-eslint-parser의 9.0 업데이트는 에러로 인해 연기
2022-05-14 21:42:24 +09:00
Hide_D 6d335284ee feat: UniqueConst에 숨겨진 hiddenSeed 생성
- 이후 RNG에 사용
2022-05-13 23:45:14 +09:00
Hide_D 1a9010ac06 fix: 안보이는 with_skin 버튼 색 부활 2022-05-13 23:01:53 +09:00
741 changed files with 48936 additions and 20976 deletions
-15
View File
@@ -1,15 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3,
"modules": false
}
]
],
"plugins": [
"lodash"
]
}
+7
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
@@ -29,6 +31,7 @@ d_pic/*.png
d_pic/*.webp
d_pic/uploaded_image
/dist_js
*/dist_misc/*
*/dist_js/*
*/dist_css/*
@@ -64,3 +67,7 @@ ingame/js/*
ingame/css/*
gateway/js/*
gateway/css/*
*.db-journal
d_log/cachegrind.*
+2 -19
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',
@@ -44,10 +41,7 @@ return [
'hwe/a_npcList.php',
'hwe/api.php',
'hwe/a_traffic.php',
'hwe/a_vote.php',
'hwe/battle_simulator.php',
'hwe/b_auction.php',
'hwe/b_battleCenter.php',
'hwe/b_betting.php',
'hwe/v_chiefCenter.php',
'hwe/b_currentCity.php',
@@ -60,10 +54,7 @@ return [
'hwe/b_myPage.php',
'hwe/v_processing.php',
'hwe/b_tournament.php',
'hwe/b_troop.php',
'hwe/c_auction.php',
'hwe/c_tournament.php',
'hwe/c_vote.php',
'hwe/func_auction.php',
'hwe/func_command.php',
'hwe/func_converter.php',
@@ -87,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',
@@ -105,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',
@@ -119,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
+14 -18
View File
@@ -8,30 +8,26 @@
],
"config": {
"platform": {
"php": "8.0"
"php": "8.3"
}
},
"require": {
"brandonwamboldt/utilphp": "^1.1",
"sergeytsalkov/meekrodb": "^2.3",
"league/plates": "^3.3",
"guzzlehttp/guzzle": "^6.3",
"monolog/monolog": "^1.23",
"firephp/firephp-core": "^0.4.0",
"sergeytsalkov/meekrodb": "^2.5",
"league/plates": "^3.5",
"vlucas/valitron": "^1.4",
"php-extended/php-tail": "^2.1",
"pguardiario/phpuri": "^1.0",
"symfony/lock": "^4.1",
"php-extended/php-tail": "^5.0",
"symfony/lock": "^6.2",
"ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^1.5",
"phan/phan": "^5.3",
"erusev/parsedown-extra": "^0.8.1",
"nette/caching": "^3.0",
"illuminate/database": "^8.61",
"illuminate/events": "^8.61",
"spatie/data-transfer-object": "^3.7",
"php-ds/php-ds": "^1.4"
"catfan/medoo": "^2.1",
"phan/phan": "^5.4",
"nette/caching": "^3.3",
"illuminate/database": "^10.0",
"illuminate/events": "^10.0",
"php-ds/php-ds": "^1.5",
"hided62/ldto": "^1.0",
"league/uri": "^6.8"
},
"autoload": {
"psr-4": {
@@ -52,6 +48,6 @@
]
},
"require-dev": {
"phpunit/phpunit": "^9.5"
"phpunit/phpunit": "^10.0"
}
}
Generated
+1557 -1927
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+15 -4
View File
@@ -81,23 +81,34 @@ a.just_link {
button.with_skin {
padding: 0 4px;
background-color: black;
background-color: #191919;
color: white;
font-size: 14px;
border-top-color: gray;
border-left-color: gray;
border-right-color: black;
border-bottom-color: black;
}
button.with_skin:disabled {
background-color: #333333;
background-color: #333;
}
input.with_skin {
background-color: black;
background-color: #191919;
color: white;
font-size: 14px;
}
input.with_skin[type=button], input.with_skin[type=submit]{
border-top-color: gray;
border-left-color: gray;
border-right-color: black;
border-bottom-color: black;
}
input.with_skin:disabled {
background-color: #333333;
background-color: #333;
}
.font0 {
+2 -1
View File
@@ -96,7 +96,8 @@ function logError(string $err, string $errstr, string $errpath, array $trace)
$fdb = FileDB::db(ROOT . '/d_log/err_log.sqlite3', ROOT . '/f_install/sql/err_log.sql');
$date = date("Ymd_His");
$err =str_replace(ROOT, '{ROOT}', $errpath);
$err = str_replace(ROOT, '{ROOT}', $err);
$errstr = str_replace(ROOT, '{ROOT}', $errstr);
$errpath = str_replace(ROOT, '{ROOT}', $errpath);
$trace = array_map(function (string $text) {
return str_replace(ROOT, '{ROOT}', $text);
+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 설정)
+2 -9
View File
@@ -17,18 +17,11 @@ if (!class_exists('\\sammo\\RootDB')) {
$rootDB = RootDB::db();
$rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) {
Json::die([
'step' => 'conn_fail'
]);
};
$rootDB->error_handler = function ($params) {
$rootDB->addHook('run_failed', function ($params) {
Json::die([
'step' => 'sql_fail'
]);
};
});
$memberCnt = $rootDB->queryFirstField('SELECT count(`NO`) from member');
if ($memberCnt == 0) {
+7 -15
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);
}
}
@@ -150,20 +150,12 @@ if (!file_exists(ROOT . '/d_setting/.htaccess')) {
$rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4');
$rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) {
$rootDB->addHook('run_failed', function ($args) {
Json::die([
'result' => false,
'reason' => 'DB 접속에 실패했습니다.'
'reason' => '에러.'. $args['error']
]);
};
$rootDB->error_handler = function ($params) {
Json::die([
'result' => false,
'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.'
]);
};
});
$mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
+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')?>
+6 -6
View File
@@ -50,9 +50,9 @@ switch ($btn) {
$db->update('general', [
'turntime' => $db->sqleval('DATE_SUB(turntime, INTERVAL %i MINUTE)', $minute)
], true);
$db->update('auction', [
'expire' => $db->sqleval('DATE_SUB(expire, INTERVAL %i MINUTE)', $minute)
], true);
$db->update('ng_auction', [
'close_date' => $db->sqleval('DATE_SUB(close_date, INTERVAL %i MINUTE)', $minute)
], 'finished = 0');
if ($locked) {
unlock();
}
@@ -78,9 +78,9 @@ switch ($btn) {
$db->update('general', [
'turntime' => $db->sqleval('DATE_ADD(turntime, INTERVAL %i MINUTE)', $minute)
], true);
$db->update('auction', [
'expire' => $db->sqleval('DATE_ADD(expire, INTERVAL %i MINUTE)', $minute)
], true);
$db->update('ng_auction', [
'close_date' => $db->sqleval('DATE_ADD(close_date, INTERVAL %i MINUTE)', $minute)
], 'finished = 0');
if ($locked) {
unlock();
}
+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;
}
+15 -51
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') ?>
@@ -48,54 +49,25 @@ $db = DB::db();
<font color=red>접속제한</font><br><b style=background-color:red;>블럭회원</b>
</td>
<td width=105 rowspan=12>
<?php
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:14px'>
<?php
$generalList = $db->query('SELECT `no`, `name`, npc, `block` FROM general ORDER BY npc, binary(`name`)');
echo "
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:14px'>";
$generalList = $db->query('SELECT `no`, `name`, npc, `block` FROM general ORDER BY npc, binary(`name`)');
foreach ($generalList 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>
<select name=weapon size=1 style='color:white;background-color:black;font-size:14px'>";
foreach (GameConst::$allItems as $itemCategories) {
foreach ($itemCategories as $item => $cnt) {
if ($cnt == 0) {
continue;
foreach ($generalList as $general) {
$style = "style=;";
if ($general['block'] > 0) {
$style .= "background-color:red;";
}
$itemObj = buildItemClass($item);
if ($itemObj->isBuyable()) {
continue;
$npcColor = getNPCColor($general['npc']);
if ($npcColor !== null) {
$style .= "color:{$npcColor};";
}
echo "<option value={$general['no']} $style>{$general['name']}</option>";
}
}
for ($i = 0; $i < 27; $i++) {
echo "
<option value={$i}>{$i}</option>";
}
?>
?>
</select>
<input type=submit name=btn value='무기지급'>
<input type=submit name=btn value='책지급'>
<input type=submit name=btn value='말지급'>
<input type=submit name=btn value='도구지급'>
</td>
</tr>
<tr>
@@ -109,10 +81,6 @@ $db = DB::db();
<td align=center>강제 사망</td>
<td><input type=submit name=btn value='강제 사망'></td>
</tr>
<tr>
<td align=center>이벤트</td>
<td><input type=submit name=btn value='특기 부여'><input type=submit name=btn value='공헌치1000'><input type=submit name=btn value='경험치1000'></td>
</tr>
<tr>
<td align=center>이벤트2</td>
<td><input type=submit name=btn value='보숙10000'><input type=submit name=btn value='궁숙10000'><input type=submit name=btn value='기숙10000'><input type=submit name=btn value='귀숙10000'><input type=submit name=btn value='차숙10000'></td>
@@ -121,10 +89,6 @@ $db = DB::db();
<td align=center>접속제한</td>
<td><input type=submit name=btn value='접속 허용'><input type=submit name=btn value='접속 제한'></td>
</tr>
<tr>
<td align=center>턴 시각 설정</td>
<td><input type=submit name=btn value='00턴'><input type=submit name=btn value='랜덤턴'></td>
</tr>
<tr>
<td align=center>명령 설정</td>
<td><input type=submit name=btn value='하야입력'><input type=submit name=btn value='방랑해산'></td>
+21 -150
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 "블럭 해제":
@@ -107,33 +109,11 @@ switch ($btn) {
'arg' => '{}',
'brief' => '휴식',
], 'general_id IN %li AND turn_idx = 0', $genlist);
break;
case "특기 부여":
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$text = "특기 부여!";
foreach ($db->query("SELECT `no`,leadership,strength,intel,dex1,dex2,dex3,dex4,dex5 FROM general WHERE `no` IN %li", $genlist) as $general) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($general['no']), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
$specialWar = SpecialityHelper::pickSpecialWar($general);
$db->update('general', [
'specage2' => $db->sqleval('age'),
'special2' => $specialWar
], 'no=%i', $general['no']);
$specialWarName = buildGeneralSpecialWarClass($specialWar)->getName();
$josaUl = JosaUtil::pick($specialWarName, '을');
$logger = new ActionLogger($general['no'], 0, $year, $month);
$logger->pushGeneralHistoryLog("특기 【<b><C>{$specialWarName}</></b>】{$josaUl} 습득");
$logger->pushGeneralActionLog("특기 【<b><L>{$specialWarName}</></b>】{$josaUl} 익혔습니다!",ActionLogger::PLAIN);
$logger->flush();
}
break;
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', [
@@ -144,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', [
@@ -155,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', [
@@ -165,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', [
@@ -176,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', [
@@ -187,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', [
@@ -198,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', [
@@ -206,111 +186,22 @@ 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;
case "무기지급":
if ($item == 'None') {
$text = "무기 회수!";
} else {
$text = getItemName($item) . " 지급!";
}
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
if ($item === 'None') {
$db->update('general', [
'weapon' => 'None'
], '`no` IN %li', $genlist);
} else {
$db->update('general', [
'weapon' => $item
], '`no` IN %li', $genlist, $item);
}
break;
case "책지급":
if ($item == 'None') {
$text = "책 회수!";
} else {
$text = getItemName($item) . " 지급!";
}
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
if ($item == 'None') {
$db->update('general', [
'book' => 'None'
], '`no` IN %li', $genlist);
} else {
$db->update('general', [
'book' => $item
], '`no` IN %li', $genlist);
}
break;
case "말지급":
if ($item == 'None') {
$text = "말 회수!";
} else {
$text = getItemName($item) . " 지급!";
}
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
if ($item == 'None') {
$db->update('general', [
'horse' => 'None'
], '`no` IN %li', $genlist);
} else {
$db->update('general', [
'horse' => $item
], '`no` IN %li', $genlist);
}
break;
case "도구지급":
if ($item == 'None') {
$text = "특수도구 회수!";
} else {
$text = getItemName($item) . " 지급!";
}
foreach ($genlist as $generalID) {
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
if ($item == 'None') {
$db->update('general', [
'item' => 'None'
], '`no` IN %li', $genlist);
} else {
$db->update('general', [
'item' => $item
], '`no` IN %li AND item < %i', $genlist, $item);
}
break;
case "하야입력":
$db->update('general_turn', [
'action' => 'che_하야',
@@ -330,26 +221,6 @@ switch ($btn) {
'brief' => '해산',
], 'general_id IN %li AND turn_idx = 1', $genlist);
break;
case "00턴":
$turnterm = $gameStor->turnterm;
foreach ($genlist as $generalID) {
$turntime = getRandTurn($turnterm);
$cutTurn = cutTurn($turntime, $turnterm);
$db->update('general', [
'turntime' => $cutTurn
], '`no` IN %li', $genlist);
}
break;
case "랜덤턴":
$turnterm = $gameStor->turnterm;
foreach ($genlist as $generalID) {
$turntime = getRandTurn($turnterm);
$db->update('general', [
'turntime' => $turntime
], '`no` IN %li', $genlist);
}
break;
}
header('location:_admin2.php');
-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);
}
+31
View File
@@ -2,7 +2,9 @@
namespace sammo;
use Ds\Set;
use sammo\Enums\RankColumn;
use sammo\Enums\AuctionType;
include "lib.php";
include "func.php";
@@ -19,18 +21,21 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("명장일람", 1);
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
?>
<!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::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>
@@ -326,6 +331,32 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates');
}
}
$dummyAuctionGeneral = [
'nation' => 0,
'no' => 0,
'ownerName' => '',
'pictureFullPath' => GetImageURL(0) . "/default.jpg",
'name' => '경매중',
'bgColor' => '#00582c',
'fgColor' => 'white',
'nationName' => '-',
];
foreach ($db->queryFirstColumn(
'SELECT `target` FROM ng_auction WHERE `finished` = 0 AND `type` = %s',
AuctionType::UniqueItem->value
) as $itemClassName) {
if(key_exists($itemClassName, $itemOwners)) {
$itemOwners[$itemClassName][] = $dummyAuctionGeneral;
}
else{
$itemOwners[$itemClassName] = [$dummyAuctionGeneral];
}
}
foreach (GameConst::$allItems as $itemType => $itemList) {
$itemNameType = $itemTypes[$itemType];
$itemList = array_reverse($itemList, true);
+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) : ?>
-434
View File
@@ -1,434 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("설문조사", 1);
$isVoteAdmin = in_array('vote', $session->acl[DB::prefix()] ?? []);
$isVoteAdmin = $isVoteAdmin || $session->userGrade >= 5;
$me = $db->queryFirstRow('SELECT no,vote from general where owner=%i', $userID);
$admin = $gameStor->getValues(['develcost', 'voteopen', 'vote_title', 'vote', 'votecomment']);
$vote_title = $admin['vote_title'] ?? '-';
$vote = $admin['vote'] ?: ['-'];
?>
<!DOCTYPE html>
<html>
<head>
<title><?= UniqueConst::$serverName ?>: 설문조사</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= 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" />
<style>
.little_bar {
float: left;
position: relative;
height: 17px;
line-height: 17px;
text-align: center;
}
</style>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printDist('ts', ['common']) ?>
<script type="text/javascript">
function captureKey(e) {
if (e.keyCode == 13 && e.srcElement.type == 'text') {
form1.btn.value = '댓글';
form1.btn.click();
return false;
}
}
</script>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td>설 문 조 사<br><?= closeButton() ?></td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<form name=form1 action=c_vote.php method=post>
<tr>
<td colspan=3 align=center class='bg2'>
<font size=5>설 문 조 사 (<?= $admin['develcost'] * 5 ?>금과 추첨으로 유니크템 증정!)</font>
</td>
</tr>
<?php
if ($isVoteAdmin) {
echo "
<tr>
<td width=48 align=center><input type=submit name=btn value='알림'></td>
<td width=98 align=center><input type=submit name=btn value='수정'></td>
<td width=848 align=left><input type=text name=title style=width:848px;></td>
</tr>
";
}
$vote_title = Tag2Code($vote_title);
echo "
<tr>
<td colspan=2 width=148 align=center class='bg1'>제 목</td>
<td width=848 align=left>&nbsp;{$vote_title}</td>
</tr>
";
$voteCount = $db->queryFirstField('SELECT count(no) FROM general WHERE vote>0 AND npc<2');
$allCount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc<2');
$percentage = round($voteCount / $allCount * 100, 1);
$voteTypeCount = count($vote);
for ($i = 1; $i < $voteTypeCount; $i++) {
echo "
<tr>
<td width=48 align=center style=color:" . getNewColor($i) . "; bgcolor=" . getVoteColor($i) . ">{$i}.</td>
<td width=98 align=center>
";
if ($me['vote'] == 0 && $me['no'] > 0) {
echo "
<input type=radio name=sel value={$i}>
";
} elseif ($admin['voteopen'] >= 1 || $isVoteAdmin) {
$vCount = $db->queryFirstField('SELECT count(no) FROM general WHERE vote=%i', $i);
$per = @round($vCount / $voteCount * 100, 1);
echo "{$vCount} 표 ({$per}%)";
} else {
echo "추후공개";
}
$vote[$i] = Tag2Code($vote[$i]);
echo "
</td>
<td align=left>&nbsp;{$vote[$i]}</td>
</tr>
";
}
echo "
<tr>
";
if ($me['vote'] == 0 && $me['no'] > 0) {
echo "
<td align=center>투표</td>
<td align=center><input type=submit name=btn value='투표'></td>
";
} else {
echo "
<td colspan=2 align=center>결산</td>
";
}
echo "
<td align=left>&nbsp;투표율 : {$voteCount} / {$allCount} ({$percentage} %)</td>
</tr>
";
if ($isVoteAdmin) {
echo "
<tr>
<td align=center><input type=submit name=btn value='리셋'></td>
<td align=center><input type=submit name=btn value='추가'></td>
<td align=left><input type=text name=str style=width:848px;></td>
</tr>
";
}
if ($admin['votecomment']) {
$comment = $admin['votecomment'];
$commentCount = count($comment);
} else {
$commentCount = 0;
}
echo "
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td colspan=4 align=center class='bg1'>댓 글</td>
</tr>
";
for ($i = 0; $i < $commentCount; $i++) {
$cmt = $comment[$i];
$cmt[2] = Tag2Code($cmt[2]);
$j = $i + 1;
echo "
<tr>
<td width=28 align=center>{$j}.</td>
<td width=130 align=center>{$cmt[0]}</td>
<td width=130 align=center>{$cmt[1]}</td>
<td width=712 align=left>&nbsp;{$cmt[2]}</td>
</tr>
";
}
if ($me['no'] > 0) {
echo "
<tr>
<td width=158 colspan=2 align=center>-</td>
<td width=130 align=center><input type=submit name=btn value='댓글'></td>
<td align=left><input type=text name=comment maxlength=60 style=width:700px; onkeydown='return captureKey(event)'></td>
</tr>
";
}
?>
</table>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td colspan=3 align=center class='bg2'>
<font size=5>
전 체 통 계
<?php
if ($isVoteAdmin) {
echo "
<input type=submit name=btn value='숨김'>
<input type=submit name=btn value='전체통계만'>
<input type=submit name=btn value='전부'>";
}
echo "
</font></td></tr>";
if ($admin['voteopen'] >= 1 || $isVoteAdmin) {
echo "
<tr>
<td width=130 align=center>전 체</td>
<td width=128 align=center>{$voteCount} / {$allCount} ({$percentage} %)</td>
<td width=742>
";
$memCount = max(1, $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2'));
$totalVote = [];
$nationVoteCount = [];
$nationVote = [];
foreach ($db->query("SELECT nation, vote, count(`no`) as cnt FROM general WHERE npc<2 GROUP BY nation, vote") as $row) {
$nation = $row['nation'];
$ownVote = $row['vote'];
$cnt = $row['cnt'];
if (!isset($totalVote[$ownVote])) {
$totalVote[$ownVote] = 0;
}
if (!isset($nationVoteCount[$nation])) {
$nationVoteCount[$nation] = 0;
$nationVote[$nation] = [];
}
if (!isset($nationVote[$nation][$ownVote])) {
$nationVote[$nation][$ownVote] = 0;
}
$totalVote[$ownVote] += $cnt;
$nationVoteCount[$nation] += $cnt;
$nationVote[$nation][$ownVote] += $cnt;
}
$totalPer = 0;
for ($i = 0; $i < $voteTypeCount; $i++) {
$per = round(($totalVote[$i] ?? 0) * 100 / $memCount, 1);
if ($i == $voteTypeCount - 1) {
$per = 100 - $totalPer;
} else {
$totalPer += $per;
}
// if($per < 5) { $vote['cnt'] = "&nbsp;"; }
?>
<?php if ($per == 0) : ?>
<?php elseif ($per < 10) : ?>
<div class='little_bar' style='width:<?= $per ?>%;color:<?= getNewColor($i) ?>;background-color:<?= getVoteColor($i) ?>;'></div>
<?php else : ?>
<div class='little_bar' style='width:<?= $per ?>%;color:<?= getNewColor($i) ?>;background-color:<?= getVoteColor($i) ?>;'><?= $totalVote[$i] ?></div>
<?php endif; ?>
<?php
}
echo "
</td>
</tr>
";
}
if ($admin['voteopen'] >= 2 || $isVoteAdmin) {
$memCount = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=0 AND npc <2');
if ($memCount == 0) {
$memCount = 1;
}
if (!isset($nationVoteCount[0])) {
$nationVoteCount[0] = 0;
}
$percentage = round($nationVoteCount[0] / $memCount * 100, 1);
echo "
<tr>
<td align=center bgcolor=black>재 야</td>
<td align=center>{$nationVoteCount[0]} / {$memCount} ({$percentage} %)</td>
<td>
";
$totalPer = 0;
for ($i = 0; $i < $voteTypeCount; $i++) {
$per = round(Util::array_get($nationVote[0][$i], 0) / $memCount * 100, 1);
if ($i == $voteTypeCount - 1) {
$per = 100 - $totalPer;
} else {
$totalPer += $per;
}
// if($per < 5) { $vote['cnt'] = "&nbsp;"; }
?>
<?php if ($per == 0) : ?>
<?php elseif ($per < 10) : ?>
<div class='little_bar' style='width:<?= $per ?>%;color:<?= getNewColor($i) ?>;background-color:<?= getVoteColor($i) ?>;'></div>
<?php else : ?>
<div class='little_bar' style='width:<?= $per ?>%;color:<?= getNewColor($i) ?>;background-color:<?= getVoteColor($i) ?>;'><?= $nationVote[0][$i] ?></div>
<?php endif; ?>
<?php
}
echo "
</td>
</tr>
";
foreach ($db->query('SELECT nation,color,name,gennum from nation order by gennum desc') as $i => $nation) {
$memCount = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=%i AND npc<2', $nation['nation']);
$voteCount = $nationVoteCount[$nation['nation']] ?? 0;
if ($memCount == 0) {
$percentage = 100;
} else {
$percentage = round($voteCount / $memCount * 100, 1);
}
echo "
<tr>
<td align=center style=color:" . newColor($nation['color']) . "; bgcolor={$nation['color']}>{$nation['name']}</td>
<td align=center>{$voteCount} / {$memCount} ({$percentage} %)</td>
<td align=center>
";
$totalPer = 0;
for ($k = 0; $k < $voteTypeCount; $k++) {
if ($memCount == 0) {
$per = 0;
continue;
}
$per = round(($nationVote[$nation['nation']][$k] ?? 0) / $memCount * 100, 1);
if ($i == $voteTypeCount - 1) {
$per = 100 - $totalPer;
} else {
$totalPer += $per;
}
// if($per < 5) { $vote['cnt'] = "&nbsp;"; }
?>
<?php if ($per == 0) : ?>
<?php elseif ($per < 10) : ?>
<div class='little_bar' style='width:<?= $per ?>%;color:<?= getNewColor($k) ?>;background-color:<?= getVoteColor($k) ?>;'></div>
<?php else : ?>
<div class='little_bar' style='width:<?= $per ?>%;color:<?= getNewColor($k) ?>;background-color:<?= getVoteColor($k) ?>;'><?= $nationVote[$nation['nation']][$k] ?? 0 ?></div>
<?php endif; ?>
<?php
}
echo "
</td>
</tr>
";
}
}
?>
</form>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td><?= closeButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
</body>
</html>
<?php
function getVoteColor($type)
{
if ($type > 0) {
$type = (($type - 1) % 7) + 1;
}
switch ($type) {
default:
case 0:
$color = "black";
break;
case 1:
$color = "red";
break;
case 2:
$color = "orange";
break;
case 3:
$color = "yellow";
break;
case 4:
$color = "green";
break;
case 5:
$color = "blue";
break;
case 6:
$color = "navy";
break;
case 7:
$color = "purple";
break;
}
return $color;
}
function getNewColor($type)
{
if ($type > 0) {
$type = (($type - 1) % 7) + 1;
}
switch ($type) {
case 2:
$color = "black";
break;
case 3:
$color = "black";
break;
default:
$color = "white";
break;
}
return $color;
}
-306
View File
@@ -1,306 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$msg = Util::getReq('msg');
$msg2 = Util::getReq('msg2');
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("거래장", 2);
$me = $db->queryFirstRow('SELECT no,special,con,turntime from general where owner=%i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
$tradeCount = $db->queryFirstField('SELECT count(no) FROM auction WHERE no1=%i', $me['no']);
$bidCount = $db->queryFirstField('SELECT count(no) FROM auction where no2=%i', $me['no']);
$btCount = $tradeCount + $bidCount;
if ($session->userGrade >= 5 || $btCount < 1) {
$btn = "submit";
} else {
$btn = "hidden";
}
if ($msg == "") {
$msg = "-";
}
if ($msg2 == "") {
$msg2 = "-";
}
?>
<!DOCTYPE html>
<html>
<head>
<title><?= UniqueConst::$serverName ?>: 거래장</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= 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']) ?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td>거 래 장<br><?= closeButton() ?></td>
</tr>
<tr>
<td align=center class='bg2'>
<font color=orange size=6><b>거 래 장</b></font><input type=button value='갱신' onclick="location.replace('b_auction.php')">
</td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<form method=post action=c_auction.php>
<tr>
<td colspan=11 align=center bgcolor=orange>
<font size=5>팝 니 다</font>
</td>
</tr>
<tr align=center class='bg1'>
<td width=68>거래번호</td>
<td width=48>선택</td>
<td width=98>판매자</td>
<td width=118>물품</td>
<td width=88>수량</td>
<td width=88>시작판매가</td>
<td width=88>현재판매가</td>
<td width=88>즉시판매가</td>
<td width=48>단가</td>
<td width=98>구매 예정자</td>
<td width=148>거래종료</td>
</tr>
<?php
$chk = 0;
foreach ($db->query('SELECT * from auction where type=0 order by expire') as $auction) {
$radio = "";
$alert = "";
$alert2 = "";
if ($auction['no1'] == $me['no']) {
$radio = " disabled";
} elseif ($auction['no2'] > 0 && $auction['amount'] * 2 <= $auction['value']) {
$radio = " disabled";
$alert = "<font color=red>";
$alert2 = "</font>";
} elseif ($auction['no2'] > 0 && $auction['topv'] <= $auction['value']) {
$radio = " disabled";
$alert = "<font color=red>";
$alert2 = "</font>";
} elseif ($chk == 0) {
$radio = " checked";
$chk = 1;
}
$pv = round($auction['value'] * 100 / $auction['amount']) / 100 + 0.001;
$pv = substr((string)$pv, 0, 4);
echo "
<tr align=center>
<td>{$auction['no']}</td>
<td><input type=radio name=sel value={$auction['no']}{$radio}></td>
<td>{$auction['name1']}</td>
<td>쌀</td>
<td>{$auction['amount']}</td>
<td>금 {$auction['cost']}</td>
<td>{$alert}금 {$auction['value']}{$alert2}</td>
<td>{$alert}금 {$auction['topv']}{$alert2}</td>
<td>{$alert}{$pv}{$alert2}</td>
<td>{$alert}{$auction['name2']}{$alert2}</td>
<td>{$auction['expire']}</td>
</tr>
";
}
?>
<tr height=25>
<td align=center class='bg1'>등록결과</td>
<td colspan=10><?= ConvertLog($msg) ?></td>
</tr>
<tr>
<td align=center class='bg1'>입찰등록</td>
<td colspan=10>
 지불할 금액: <input type=text style=color:white;background-color:black; size=6 maxlength=6 name=value>
<input type=<?= $btn ?> name=btn value='구매시도' onclick='return confirm("정말 입찰하시겠습니까?");'>
</td>
</tr>
<tr>
<td align=center class='bg1'>거래등록</td>
<td colspan=10>
 종료: <input type=text style=color:white;background-color:black; size=2 maxlength=2 name=term value=12>턴 후
 물품: 쌀
 판매량: <input type=text style=color:white;background-color:black; size=5 maxlength=5 name=amount value=1000>
 시작가: <input type=text style=color:white;background-color:black; size=5 maxlength=5 name=cost value=500>
 즉구가: <input type=text style=color:white;background-color:black; size=5 maxlength=5 name=topv value=2000>
<input type=<?= $btn ?> name=btn value='판매' onclick='return confirm("정말 판매하시겠습니까?");'>
</td>
</tr>
<tr>
<td colspan=11>
ㆍ<font color=cyan>Hint</font>) 거래자가 판매(물품 판매, 금 수령), 입찰자가 구매(물품 구입, 금 지불).<br>
ㆍ<font color=cyan>Hint</font>) 단가가 1.00보다 높을수록 판매자 유리.<br>
ㆍ<font color=cyan>Hint</font>) 단가가 1.00보다 낮을수록 입찰자 유리.<br>
</td>
</tr>
</form>
</table>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<form method=post action=c_auction.php>
<tr>
<td colspan=11 align=center bgcolor=skyblue>
<font size=5>삽 니 다</font>
</td>
</tr>
<tr align=center class='bg1'>
<td width=68>거래번호</td>
<td width=48>선택</td>
<td width=98>구매자</td>
<td width=118>물품</td>
<td width=88>수량</td>
<td width=88>시작구매가</td>
<td width=88>현재구매가</td>
<td width=88>즉시구매가</td>
<td width=48>단가</td>
<td width=98>판매 예정자</td>
<td width=148>거래종료</td>
</tr>
<?php
$chk = 0;
foreach ($db->query('SELECT * from auction where type=1 order by expire') as $auction) {
$radio = "";
$alert = "";
$alert2 = "";
if ($auction['no1'] == $me['no']) {
$radio = " disabled";
} elseif ($auction['no2'] > 0 && $auction['amount'] >= $auction['value'] * 2) {
$radio = " disabled";
$alert = "<font color=red>";
$alert2 = "</font>";
} elseif ($auction['no2'] > 0 && $auction['topv'] >= $auction['value']) {
$radio = " disabled";
$alert = "<font color=red>";
$alert2 = "</font>";
} elseif ($chk == 0) {
$radio = " checked";
$chk = 1;
}
$pv = round($auction['value'] * 100 / $auction['amount']) / 100 + 0.001;
$pv = substr((string)$pv, 0, 4);
echo "
<tr align=center>
<td>{$auction['no']}</td>
<td><input type=radio name=sel value={$auction['no']}{$radio}></td>
<td>{$auction['name1']}</td>
<td>쌀</td>
<td>{$auction['amount']}</td>
<td>금 {$auction['cost']}</td>
<td>{$alert}금 {$auction['value']}{$alert2}</td>
<td>{$alert}금 {$auction['topv']}{$alert2}</td>
<td>{$alert}{$pv}{$alert2}</td>
<td>{$alert}{$auction['name2']}{$alert2}</td>
<td>{$auction['expire']}</td>
</tr>
";
}
?>
<tr height=25>
<td align=center class='bg1'>등록결과</td>
<td colspan=10><?= ConvertLog($msg2) ?></td>
</tr>
<tr>
<td align=center class='bg1'>입찰등록</td>
<td colspan=10>
 수령할 금액: <input type=text style=color:white;background-color:black; size=6 maxlength=6 name=value>
<input type=<?= $btn ?> name=btn value='판매시도' onclick='return confirm("정말 입찰하시겠습니까?");'>
</td>
</tr>
<tr>
<td align=center class='bg1'>거래등록</td>
<td colspan=10>
 종료: <input type=text style=color:white;background-color:black; size=2 maxlength=2 name=term value=12>턴 후
 물품: 쌀
 구입량: <input type=text style=color:white;background-color:black; size=5 maxlength=5 name=amount value=1000>
 시작가: <input type=text style=color:white;background-color:black; size=5 maxlength=5 name=cost value=2000>
 즉구가: <input type=text style=color:white;background-color:black; size=5 maxlength=5 name=topv value=500>
<input type=<?= $btn ?> name=btn value='구매' onclick='return confirm("정말 구매하시겠습니까?");'>
</td>
</tr>
<tr>
<td colspan=11>
ㆍ<font color=cyan>Hint</font>) 거래자가 구매(물품 구매, 금 지불), 입찰자가 판매(물품 판매, 금 수령).<br>
ㆍ<font color=cyan>Hint</font>) 단가가 1.00보다 낮을수록 구매자 유리.<br>
ㆍ<font color=cyan>Hint</font>) 단가가 1.00보다 높을수록 입찰자 유리.<br>
</td>
</tr>
</form>
</table>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td align=center class='bg2'>
<font size=5>최 근 기 록</font>
</td>
</tr>
<tr>
<td>
<?= getAuctionLogRecent(20) ?>
</td>
</tr>
<tr>
<td align=center class='bg2'>
<font size=5>도 움 말</font>
</td>
</tr>
<tr>
<td>
<font color=white size=2>
ㆍ판매거래는 거래자가 판매할 물품을 거래하면, 구입을 희망하는 사람이 현재가보다 높게 입찰하여 구입하는 방식입니다.<br>
ㆍ<font color=cyan>Hint</font>) 쌀이 귀한 경우는 입찰자가 많아서 자연스레 단가가 오르게 됩니다. (해당 물품을 사려는 가격이 오름)<br>
ㆍ<font color=cyan>Hint</font>) 쌀이 흔한 경우는 초기 가격을 낮게 책정해야 판매가 가능할 겁니다.<br>
ㆍ구매거래는 거래자가 구입할 물품을 거래하면, 판매를 희망하는 사람이 현재가보다 낮게 입찰하여 판매하는 방식입니다.<br>
ㆍ<font color=cyan>Hint</font>) 쌀이 흔한 경우는 입찰자가 많아서 자연스레 단가가 내리게 됩니다. (해당 물품을 팔려는 가격이 내림)<br>
ㆍ<font color=cyan>Hint</font>) 쌀이 귀한 경우는 초기 가격을 높게 책정해야 구입이 가능할 겁니다.<br>
ㆍ마감임박때 입찰하는 경우 입찰후 1턴 후로 종료시간이 연장됩니다.<br>
ㆍ즉시구매가로 입찰하는 경우 입찰후 1턴 후로 종료시간이 결정됩니다.<br>
ㆍ악용 방지를 위해 50% ~ 200%의 가격에서 거래시작이 가능합니다.<br>
ㆍ악용 방지를 위해 즉시판매가는 110% 이상, 즉시구매가는 90% 이하의 시세로 가능합니다.<br>
ㆍ악용 방지를 위해 즉시판매가는 시작판매가의 110% 이상, 즉시구매가는 시작구매가의 90% 이하로 가능합니다.<br>
ㆍ1인당 도합 1건의 거래와 입찰이 가능합니다.<br>
ㆍ기본금쌀 1000은 거래에 사용되지 못합니다.<br>
ㆍ유찰될 때는 거래 과실자에게 거래금의 1%가 벌금으로 부과됩니다.<br>
ㆍ<font color=magenta>10단위로 거래가 가능합니다. 1자리는 반올림 처리 됩니다.</font><br>
ㆍ<font color=red>★ 최고가 거래 ★</font> 혹은 <font color=red>★ 최저가 거래 ★</font> 는 암거래 및 악용의 가능성이니 감시 부탁드립니다.<br>
ㆍ거래와 입찰은 취소가 불가능하니 주의하세요!<br>
ㆍ<font color=cyan>Hint</font>) 단가는 금/쌀로 쌀1을 거래하기 위한 금의 양입니다.<br>
ㆍ<font color=cyan>Hint</font>) 단가가 높으면(>1.00) 쌀이 비싸므로 판매가 이득입니다.<br>
ㆍ<font color=cyan>Hint</font>) 단가가 낮으면(<1.00) 금이 비싸므로 구매가 이득입니다.<br>
ㆍ즐거운 거래!
</font>
</td>
</tr>
<tr>
<td><?= closeButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
</body>
</html>
-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 "><?= backButton() ?></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>
+49 -48
View File
@@ -25,12 +25,24 @@ if ($meLevel == 0) {
$nation = $db->queryFirstRow('SELECT nation,name,level,color,chief_set from nation where nation=%i', $nationID); //국가정보
if ($meLevel >= 5) {
$candidateStrength = $db->query('SELECT no,name,officer_level,city,npc from general where nation=%i and officer_level!=12 and strength>=%i order by npc,binary(name)', $nationID, GameConst::$chiefStatMin);
$candidateIntel = $db->query('SELECT no,name,officer_level,city,npc from general where nation=%i and officer_level!=12 and intel>=%i order by npc,binary(name)', $nationID, GameConst::$chiefStatMin);
$candidateAny = $db->query('SELECT no,name,officer_level,city,npc,leadership,strength,intel,killturn from general where nation=%i and officer_level!=12 order by npc,binary(name)', $nationID); //추방 때문에 조금 더 김
} else {
$candidateStrength = [];
$candidateIntel = [];
$candidateAny = [];
}
?>
<!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=1024" />
<title><?= UniqueConst::$serverName ?>: 인사부</title>
@@ -43,6 +55,7 @@ $nation = $db->queryFirstRow('SELECT nation,name,level,color,chief_set from nati
var chiefStatMin = <?= GameConst::$chiefStatMin ?>;
var myLevel = <?= $meLevel ?>;
</script>
<?= WebUtil::printDist('vue', [], true) ?>
<?= WebUtil::printDist('ts', ['common', 'bossInfo']) ?>
<?php
@@ -180,61 +193,21 @@ $nation = $db->queryFirstRow('SELECT nation,name,level,color,chief_set from nati
<td colspan=5><?= $eaglestr ?></td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td colspan=6 height=5></td>
<td colspan=4 height=5></td>
</tr>
<tr>
<td colspan=2 align=center bgcolor=red>추 방</td>
<td colspan=4 align=center bgcolor=blue>수 뇌 부 임 명</td>
</tr>
<tr>
<td width=498 align=right class='bg1'>대상 장수</td>
<td width=498>
<?php $officerLevelText = getOfficerLevelText(11, $nation['level']); ?>
<td width=98 align=right class='bg1'><?= getOfficerLevelText(12, $nation['level']) ?></td>
<td width=398><?= $level[12]['name'] ?> 【<?= CityConst::byID($level[12]['city'])->name ?>】</td>
<td width=98 align=right class='bg1'><?= $officerLevelText ?></td>
<td width=398>
<?php
if ($meLevel >= 5) {
$candidateStrength = $db->query('SELECT no,name,officer_level,city,npc from general where nation=%i and officer_level!=12 and strength>=%i order by npc,binary(name)', $nationID, GameConst::$chiefStatMin);
$candidateIntel = $db->query('SELECT no,name,officer_level,city,npc from general where nation=%i and officer_level!=12 and intel>=%i order by npc,binary(name)', $nationID, GameConst::$chiefStatMin);
$candidateAny = $db->query('SELECT no,name,officer_level,city,npc,leadership,strength,intel,killturn from general where nation=%i and officer_level!=12 order by npc,binary(name)', $nationID); //추방 때문에 조금 더 김
} else {
$candidateStrength = [];
$candidateIntel = [];
$candidateAny = [];
}
if ($meLevel >= 5 && !isOfficerSet($nation['chief_set'], $meLevel)) {
echo "
<select id='genlist_kick' size=1 style=color:white;background-color:black;>";
foreach ($candidateAny as $general) {
if ($general['no'] === $me['no']) {
continue;
}
echo "
<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} <small>({$general['leadership']}/{$general['strength']}/{$general['intel']}, {$general['killturn']}턴)</small></option>";
}
echo "
</select>
<input type=$btn id='btn_kick' value=추방>";
}
$officerLevelText = getOfficerLevelText(11, $nation['level']);
echo "
</td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td colspan=4 height=5></td></tr>
<tr><td colspan=4 align=center bgcolor=blue>수 뇌 부 임 명</td></tr>
<tr>
<td width=98 align=right class='bg1'>" . getOfficerLevelText(12, $nation['level']) . "</td>
<td width=398>{$level[12]['name']} 【" . CityConst::byID($level[12]['city'])->name . "】</td>
<td width=98 align=right class='bg1'>{$officerLevelText}</td>
<td width=398>
";
if ($meLevel >= 5 && !isOfficerSet($nation['chief_set'], 11)) {
echo "
<select id='genlist_11' size=1 maxlength=15 style=color:white;background-color:black;>
@@ -553,6 +526,34 @@ $nation = $db->queryFirstRow('SELECT nation,name,level,color,chief_set from nati
<td colspan=5>※ <font color=orange>노란색</font>은 변경 불가능, 하얀색은 변경 가능 관직입니다.</td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td colspan=6 height=5></td>
</tr>
<tr>
<td colspan=2 align=center bgcolor=red>추 방</td>
</tr>
<tr>
<td width=498 align=right class='bg1'>대상 장수</td>
<td width=498>
<?php
if ($meLevel >= 5 && !isOfficerSet($nation['chief_set'], $meLevel)) : ?>
<select id='genlist_kick' size=1 style=color:white;background-color:black;>";
<?php foreach ($candidateAny as $general) : ?>
<?php if ($general['no'] === $me['no']) {
continue;
}
?>
<option data-officer_level='<?= $general['officer_level'] ?>' data-name='<?= $general['name'] ?>' value='<?= $general['no'] ?>'><?= $general['name'] ?> <small>(<?= $general['leadership'] ?>/<?= $general['strength'] ?>/<?= $general['intel'] ?>, <?= $general['killturn'] ?>턴)</small></option>
<?php endforeach; ?>
</select>
<input type=<?= $btn ?> id='btn_kick' value=추방>
<?php endif; ?>
</td>
</tr>
</table>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
+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>
+64 -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,11 +135,22 @@ $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>
∞<span style='color:orange'>설정저장은 이달중 <?= $myset ?>회 남았습니다.</span><br><br>
<?php if ($me->getPenaltyList()->count()) : ?>
징계 목록(저장 시 갱신)<br>
<?php foreach ($me->getPenaltyList() as $penaltyKey => $penalty) : ?>
<span style='color:red'><?= $penaltyKey->getHelptext() ?> : <?= $penalty ?></span><br>
<?php endforeach; ?>
<br />
<?php endif; ?>
<?php if (!($gameStor->autorun_user['limit_minutes'] ?? false)) : ?>
휴 가 신 청<br>
<button type="button" id='vacation' style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;height:30px;font-size:14px;>휴가 신청</button><br><br>
@@ -122,9 +158,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 +201,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 +212,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 +225,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 +239,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 +249,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>
-247
View File
@@ -1,247 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$v = new Validator($_POST + $_GET);
$v->rule('integer', [
'amount',
'cost',
'topv',
'value',
'term',
'sel'
]);
$btn = Util::getPost('btn');
$amount = Util::getPost('amount', 'int');
$cost = Util::getPost('cost', 'int');
$topv = Util::getPost('topv', 'int');
$value = Util::getPost('value', 'int');
$term = Util::getPost('term', 'int');
$sel = Util::getPost('sel', 'int');
$msg = '';
$msg2 = '';
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("입찰", 1);
$turnterm = $gameStor->turnterm;
$me = $db->queryFirstRow('SELECT no,name,gold,rice,special from general where owner=%i', $userID);
$tradeCount = $db->queryFirstField('SELECT count(no) FROM auction WHERE no1=%i', $me['no']);
$bidCount = $db->queryFirstField('SELECT count(no) FROM auction WHERE no2=%i', $me['no']);
$btCount = $tradeCount + $bidCount;
$unit = $turnterm * 60;
$amount = Util::round($amount, -1);
$cost = Util::round($cost, -1);
$topv = Util::round($topv, -1);
$value = Util::round($value, -1);
if ($term > 24) {
$term = 24;
}
$valid = 1;
if ($session->userGrade >= 5 || $btCount < 1) {
} else {
$msg = "ㆍ<span class='ev_warning'>더이상 등록할 수 없습니다.</span>";
$msg2 = "ㆍ<span class='ev_warning'>더이상 등록할 수 없습니다.</span>";
$valid = 0;
$btn = "hidden";
}
if ($btn == "판매") {
if ($term < 0 || $term > 24) {
$msg = "ㆍ<span class='ev_warning'>종료기한은 1 ~ 24 턴 이어야 합니다.</span>";
$valid = 0;
}
if ($amount < 100 || $amount > 10000) {
$msg = "ㆍ<span class='ev_warning'>거래량은 100 ~ 10000 이어야 합니다.</span>";
$valid = 0;
}
if ($cost > $amount * 2 || $cost * 2 < $amount) {
$msg = "ㆍ<span class='ev_warning'>시작판매가는 50% ~ 200% 이어야 합니다.</span>";
$valid = 0;
}
if ($topv * 10 < $amount * 11 || $topv > $amount * 2) {
$msg = "ㆍ<span class='ev_warning'>즉시판매가는 110% ~ 200% 이어야 합니다.</span>";
$valid = 0;
}
if ($topv * 10 < $cost * 11) {
$msg = "ㆍ<span class='ev_warning'>즉시판매가는 시작판매가의 110% 이상이어야 합니다.</span>";
$valid = 0;
}
if ($amount > $me['rice'] - GameConst::$defaultRice) {
$msg = "ㆍ<span class='ev_warning'>기본 군량 ".GameConst::$defaultRice."은 거래할 수 없습니다.</span>";
$valid = 0;
}
if ($valid == 1) {
$msg = "ㆍ<span class='ev_success'>등록 성공.</span>";
$date = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s")) + $unit * $term);
$db->insert('auction', [
'type'=>0,
'no1'=>$me['no'],
'name1'=>$me['name'],
'amount'=>$amount,
'cost'=>$cost,
'value'=>$cost,
'topv'=>$topv,
'expire'=>$date
]);
}
} elseif ($btn == "구매시도") {
$auction = $db->queryFirstRow('SELECT no2,value,topv,expire,amount FROM auction WHERE no=%i LIMIT 1', $sel);
if ($value == $auction['topv']) {
$valid = 2;
}
if (!$auction) {
$msg = "ㆍ<span class='ev_warning'>종료된 거래입니다.</span>";
$valid = 0;
}
if ($auction['no2'] > 0 && $value <= $auction['value']) {
$msg = "ㆍ<span class='ev_warning'>현재판매가보다 높게 입찰해야 합니다.</span>";
$valid = 0;
}
if ($value < $auction['value']) {
$msg = "ㆍ<span class='ev_warning'>현재판매가보다 높게 입찰해야 합니다.</span>";
$valid = 0;
}
if ($value > $auction['topv']) {
$msg = "ㆍ<span class='ev_warning'>즉시판매가보다 높을 수 없습니다.</span>";
$valid = 0;
}
if ($value > $me['gold'] - GameConst::$defaultGold) {
$msg = "ㆍ<span class='ev_warning'>기본 자금 ".GameConst::$defaultGold."은 거래할 수 없습니다.</span>";
$valid = 0;
}
if ($valid == 1) {
$msg = "ㆍ<span class='ev_success'>입찰 성공.</span> 거래완료는 빨라도 현재로부터 1턴 뒤입니다.";
$date = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s")) + $unit);
if ($auction['expire'] > $date) {
$date = $auction['expire'];
}
$db->update('auction', [
'value'=>$value,
'no2'=>$me['no'],
'name2'=>$me['name'],
'expire'=>$date,
], 'no=%i', $sel);
} elseif ($valid == 2) {
$msg = "ㆍ<span class='ev_success'>즉시판매 성공.</span> 거래완료는 빨라도 현재로부터 1턴 뒤입니다.";
$date = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s")) + $unit);
$db->update('auction', [
'value'=>$value,
'no2'=>$me['no'],
'name2'=>$me['name'],
'expire'=>$date,
], 'no=%i', $sel);
}
} elseif ($btn == "구매") {
if ($term < 0 || $term > 24) {
$msg2 = "ㆍ<span class='ev_warning'>종료기한은 1 ~ 24 턴 이어야 합니다.</span>";
$valid = 0;
}
if ($amount < 100 || $amount > 10000) {
$msg2 = "ㆍ<span class='ev_warning'>거래량은 100 ~ 10000 이어야 합니다.</span>";
$valid = 0;
}
if ($cost > $amount * 2 || $cost * 2 < $amount) {
$msg2 = "ㆍ<span class='ev_warning'>시작구매가는 50% ~ 200% 이어야 합니다.</span>";
$valid = 0;
}
if ($topv < $amount * 0.5 || $topv > $amount * 0.9) {
$msg2 = "ㆍ<span class='ev_warning'>즉시구매가는 50% ~ 90% 이어야 합니다.</span>";
$valid = 0;
}
if ($topv > $cost * 0.9) {
$msg2 = "ㆍ<span class='ev_warning'>즉시구매가는 시작구매가의 90% 이하이어야 합니다.</span>";
$valid = 0;
}
if ($cost > $me['gold'] - GameConst::$defaultGold) {
$msg2 = "ㆍ<span class='ev_warning'>기본 자금 ".GameConst::$defaultGold."은 거래할 수 없습니다.</span>";
$valid = 0;
}
if ($valid == 1) {
$msg2 = "ㆍ<span class='ev_success'>등록 성공.</span>";
$date = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s")) + $unit * $term);
$db->insert('auction', [
'type'=>1,
'no1'=>$me['no'],
'name1'=>$me['name'],
'amount'=>$amount,
'cost'=>$cost,
'value'=>$cost,
'topv'=>$topv,
'expire'=>$date
]);
}
} elseif ($btn == "판매시도") {
$auction = $db->queryFirstRow('SELECT no2,value,topv,expire,amount FROM auction WHERE no=%i LIMIT 1', $sel);
if ($value == $auction['topv']) {
$valid = 2;
}
if (!$auction) {
$msg2 = "ㆍ<span class='ev_warning'>종료된 거래입니다.</span>";
$valid = 0;
}
if ($auction['no2'] > 0 && $value >= $auction['value']) {
$msg2 = "ㆍ<span class='ev_warning'>현재구매가보다 낮게 입찰해야 합니다.</span>";
$valid = 0;
}
if ($value > $auction['value']) {
$msg2 = "ㆍ<span class='ev_warning'>현재구매가보다 낮게 입찰해야 합니다.</span>";
$valid = 0;
}
if ($value < $auction['topv']) {
$msg2 = "ㆍ<span class='ev_warning'>즉시구매가보다 낮을 수 없습니다.</span>";
$valid = 0;
}
if ($value > $me['rice'] - GameConst::$defaultRice) {
$msg2 = "ㆍ<span class='ev_warning'>기본 군량 ".GameConst::$defaultRice."은 거래할 수 없습니다.</span>";
$valid = 0;
}
if ($valid == 1) {
$msg2 = "ㆍ<span class='ev_success'>입찰 성공.</span> 거래완료는 빨라도 현재로부터 1턴 뒤입니다.";
$date = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s")) + $unit);
if ($auction['expire'] > $date) {
$date = $auction['expire'];
}
$db->update('auction', [
'value'=>$value,
'no2'=>$me['no'],
'name2'=>$me['name'],
'expire'=>$date,
], 'no=%i', $sel);
} elseif ($valid == 2) {
$msg2 = "ㆍ<span class='ev_success'>즉시구매 성공.</span> 거래완료는 빨라도 현재로부터 1턴 뒤입니다.";
$date = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s")) + $unit);
$db->update('auction', [
'value'=>$value,
'no2'=>$me['no'],
'name2'=>$me['name'],
'expire'=>$date,
], 'no=%i', $sel);
}
}
Submit("b_auction.php", $msg, $msg2);
+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 == "랜덤투입") {
-91
View File
@@ -1,91 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$btn = Util::getPost('btn');
$sel = Util::getPost('sel', 'int');
$comment = Util::getPost('comment');
$title = Util::getPost('title');
$str = Util::getPost('str');
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$isVoteAdmin = in_array('vote', $session->acl[DB::prefix()]??[]);
$isVoteAdmin = $isVoteAdmin || $session->userGrade >= 5;
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['develcost', 'cost', 'vote_title', 'vote', 'votecomment']);
$generalID = Session::getGeneralID();
$general = General::createGeneralObjFromDB($generalID, ['vote','horse','weapon','book','item','npc','imgsvr','picture','aux'], 2);
if($btn == "투표" && $general->getVar('vote') == 0 && $sel > 0) {
$develcost = $admin['develcost'] * 5;
$db->update('general', [
'gold'=>$db->sqleval('gold + %i', $develcost),
'vote'=>$sel
], 'owner=%i', $userID);
if(tryUniqueItemLottery($general, '설문조사')){
$general->applyDB($db);
}
}
else if($btn == "댓글" && trim($comment) != "") {
$comment = StringUtil::neutralize($comment);
$nation = $general->getStaticNation();
if(!$admin['votecomment']){
$admin['votecomment'] = [];
}
$admin['votecomment'][] = [$nation['name'],$general->getName(),$comment];
$gameStor->votecomment = $admin['votecomment'];
}
if(!$isVoteAdmin){
header('location:a_vote.php', true, 303);
die();
}
if($btn == "수정") {
if($title != "") {
$gameStor->vote_title = WebUtil::htmlPurify($title);
}
} elseif($btn == "추가") {
if($str != "") {
if(!$admin['vote']){
$admin['vote'] = [];
}
$admin['vote'][] = WebUtil::htmlPurify($str);
$gameStor->vote=$admin['vote'];
}
} elseif($btn == "리셋") {
$gameStor->voteopen=1;
$gameStor->vote=['-'];
$gameStor->vote_title = '-';
$gameStor->votecomment=[];
$db->update('general', [
'vote'=>0
], true);
} elseif($btn == "알림") {
$db->update('general', [
'newvote'=>1
], 'vote=0');
} elseif($btn == "숨김") {
$gameStor->voteopen = 0;
} elseif($btn == "전체통계만") {
$gameStor->voteopen = 1;
} elseif($btn == "전부") {
$gameStor->voteopen = 2;
}
header('location:a_vote.php', true, 303);
+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를 제거한 복사본을 만들고 수정
}
+1
View File
@@ -5,6 +5,7 @@ class UniqueConst{
public static $serverID = '_tK_serverID_';
public static $serverName = '_tK_serverName_';
public static $seasonIdx = '_tK_seasonIdx_';
public static $hiddenSeed = '_tK_hiddenSeed_';
private function __construct(){}
+185 -434
View File
@@ -3,9 +3,14 @@
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\PenaltyKey;
use sammo\Enums\RankColumn;
use sammo\Event\Action;
require_once 'process_war.php';
require_once 'func_gamerule.php';
@@ -102,10 +107,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) {
@@ -115,15 +119,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;
@@ -135,18 +139,18 @@ function getBlockLevel()
return DB::db()->queryFirstField('select block from general where no = %i', Session::getInstance()->generalID);
}
function getRandGenName()
function getRandGenName(RandUtil $rng)
{
$firstname = Util::choiceRandom(GameConst::$randGenFirstName);
$middlename = Util::choiceRandom(GameConst::$randGenMiddleName);
$lastname = Util::choiceRandom(GameConst::$randGenLastName);
$firstname = $rng->choice(GameConst::$randGenFirstName);
$middlename = $rng->choice(GameConst::$randGenMiddleName);
$lastname = $rng->choice(GameConst::$randGenLastName);
return "{$firstname}{$middlename}{$lastname}";
}
function cityInfo(General $generalObj)
function cityInfo(GeneralLite $generalObj)
{
$db = DB::db();
@@ -373,11 +377,11 @@ function myNationInfo(General $generalObj)
function checkSecretMaxPermission($penalty)
{
$secretMax = 4;
if ($penalty['noTopSecret'] ?? false) {
if ($penalty[PenaltyKey::NoTopSecret->value] ?? false) {
$secretMax = 1;
} else if ($penalty['noChief'] ?? false) {
} else if ($penalty[PenaltyKey::NoChief->value] ?? false) {
$secretMax = 1;
} else if ($penalty['noAmbassador'] ?? false) {
} else if ($penalty[PenaltyKey::NoAmbassador->value] ?? false) {
$secretMax = 2;
}
return $secretMax;
@@ -400,19 +404,19 @@ function checkSecretPermission(array $me, $checkSecretLimit = true)
}
if ($penalty['noSecret'] ?? false) {
if ($penalty[PenaltyKey::NoChief->value] ?? false) {
return 0;
}
$secretMin = 0;
$secretMax = checkSecretMaxPermission($me, $penalty);
$secretMax = checkSecretMaxPermission($penalty);
if ($me['officer_level'] == 12) {
$secretMin = 4;
} else if ($me['permission'] == 'ambassador') {
} else if ($permission == 'ambassador') {
$secretMin = 4;
} else if ($me['permission'] == 'auditor') {
} else if ($permission == 'auditor') {
$secretMin = 3;
} else if ($me['officer_level'] >= 5) {
$secretMin = 2;
@@ -641,7 +645,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>";
@@ -750,7 +754,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>";
}
@@ -884,7 +888,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)
@@ -904,7 +908,7 @@ function nationMsg(General $general)
$nationID = $general->getNationID();
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
return $nationStor->notice ?? '';
return $nationStor->nationNotice['msg'] ?? '';
}
function banner()
@@ -997,76 +1001,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()
@@ -1074,12 +1071,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'];
}
@@ -1090,22 +1084,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()
@@ -1113,13 +1105,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) * GameConst::$refreshLimitCoef;
if ($con != $conlimit) {
$gameStor->conlimit = $con;
if ($nextRefreshLimit != $refreshLimit) {
$gameStor->refreshLimit = $nextRefreshLimit;
}
}
@@ -1204,9 +1196,9 @@ function checkDelay()
$db->update('general', [
'turntime' => $db->sqleval('DATE_ADD(turntime, INTERVAL %i MINUTE)', $minute)
], 'turntime<=DATE_ADD(turntime, INTERVAL %i MINUTE)', $term);
$db->update('auction', [
'expire' => $db->sqleval('DATE_ADD(expire, INTERVAL %i MINUTE)', $minute)
], true);
$db->update('ng_auction', [
'close_date' => $db->sqleval('DATE_ADD(close_date, INTERVAL %i MINUTE)', $minute)
], 'finished = 0');
}
}
@@ -1221,10 +1213,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');
@@ -1247,74 +1247,6 @@ function updateOnline()
$gameStor->online_nation = join(', ', $onlineNation);
}
function addAge()
{
$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(
$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(
$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();
@@ -1343,7 +1275,7 @@ function turnDate($curtime)
}
function triggerTournament()
function triggerTournament(RandUtil $rng)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -1354,10 +1286,10 @@ function triggerTournament()
if ($tournament != 0) {
return;
}
if ($tnmt_trig == 0) {
if (!$tnmt_trig) {
return;
}
if (!Util::randBool(0.4)) {
if (!$rng->nextBool(0.4)) {
return;
}
@@ -1370,7 +1302,7 @@ function triggerTournament()
$tnmt_type = array_pop($tnmt_pattern);
$gameStor->setValue('tnmt_pattern', $tnmt_pattern);
startTournament($tnmt_trig, $tnmt_type);
startTournament($tnmt_type);
}
function CheckHall($no)
@@ -1406,7 +1338,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);
@@ -1552,9 +1484,10 @@ function CheckHall($no)
}
}
function giveRandomUniqueItem(General $general, string $acquireType): bool
function giveRandomUniqueItem(RandUtil $rng, General $general, string $acquireType): bool
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
//아이템 습득 상황
$availableUnique = [];
@@ -1586,6 +1519,18 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
}
}
$auctionItems = $db->queryFirstColumn(
'SELECT `target` FROM `ng_auction` WHERE `type` = %s AND `finished` = 0',
AuctionType::UniqueItem->value
);
foreach ($auctionItems as $itemCode) {
if (key_exists($itemCode, $occupiedUnique)) {
$occupiedUnique[$itemCode]++;
} else {
$occupiedUnique[$itemCode] = 1;
}
}
foreach ($db->queryAllLists('SELECT namespace, count(*) as cnt FROM `storage` WHERE namespace LIKE "ut_%" GROUP BY namespace') as [$uniqueNS, $cnt]) {
$itemCode = substr($uniqueNS, 3);
$itemClass = buildItemClass($itemCode);
@@ -1629,10 +1574,7 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
return false;
}
if ($general->getAuxVar('inheritRandomUnique')) {
$gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month, $initYear, $initMonth] = $gameStor->getValuesAsArray(['year', 'month', 'init_year', 'init_month']);
$relMonthByInit = Util::joinYearMonth($year, $month) - Util::joinYearMonth($initYear, $initMonth);
@@ -1643,7 +1585,7 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
}
}
[$itemType, $itemCode] = Util::choiceRandomUsingWeightPair($availableUnique);
[$itemType, $itemCode] = $rng->choiceUsingWeightPair($availableUnique);
$nationName = $general->getStaticNation()['name'];
$generalName = $general->getName();
@@ -1666,211 +1608,7 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
return true;
}
function rollbackInheritUniqueTrial(General $general, string $itemKey, string $reason)
{
$ownerID = $general->getVar('owner');
$db = DB::db();
$itemTrials = $general->getAuxVar('inheritUniqueTrial');
LogText("선택유니크 롤백:{$ownerID}", [$itemKey, $itemTrials]);
unset($itemTrials[$itemKey]);
if (count($itemTrials) == 0) {
$itemTrials = null;
}
$general->setAuxVar('inheritUniqueTrial', $itemTrials);
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}");
$ownTrial = $trialStor->getValue("u{$ownerID}");
$itemObj = buildItemClass($itemKey);
$itemName = $itemObj->getName();
if ($ownTrial) {
//두 값이 general, KVStorage 둘다 있고, 이중에선 KVStorage 값을 기준으로 하자 따르자
[,, $amount] = $ownTrial;
$trialStor->deleteValue("u{$ownerID}");
$general->increaseInheritancePoint(InheritanceKey::previous, $amount);
$general->increaseRankVar(RankColumn::inherit_point_spent_dynamic, -$amount);
LogText("선택유니크 롤백포인트:{$ownerID}", $amount);
$userLogger = new UserLogger($ownerID);
$userLogger->push("{$itemName} 입찰에 사용한 {$amount} 포인트 반환", "inheritPoint");
}
//메시지
$staticNation = $general->getStaticNation();
$unlimited = new \DateTime('9999-12-31');
$src = new MessageTarget(0, '', 0, 'System', '#000000');
$dest = new MessageTarget($general->getID(), $general->getName(), $general->getNationID(), $staticNation['name'], $staticNation['color'], GetImageURL($general->getVar('imgsvr'), $general->getVar('picture')));
$josaUl = JosaUtil::pick($itemName, '을');
$msg = new Message(
Message::MSGTYPE_PRIVATE,
$src,
$dest,
"{$itemName}{$josaUl} 얻지 못했습니다. {$reason}",
new DateTime(),
$unlimited,
[]
);
$general->applyDB($db);
$msg->send(true);
}
function tryRollbackInheritUniqueItem(General $general): void
{
tryInheritUniqueItem($general, 'Rollback', true);
}
function tryInheritUniqueItem(General $general, string $acquireType = '아이템', bool $justRollback = false): bool
{
$ownerID = $general->getVar('owner');
if (!$ownerID) {
LogText("선택유니크 실패???: {$ownerID}", $general->getName());
return false;
}
$itemTrials = $general->getAuxVar('inheritUniqueTrial') ?? [];
arsort($itemTrials);
LogText("선택유니크항목: {$ownerID}", $itemTrials);
$db = DB::db();
$ownTarget = null;
$ownType = null;
foreach ($itemTrials as $itemKey => $amount) {
$availableItemTypes = [];
$reasons = [];
foreach (GameConst::$allItems as $itemType => $itemList) {
//아직은 그런 경우는 없지만 동일 유니크를 여러 부위에 장착할 수 있을지도 모름
if (!key_exists($itemKey, $itemList)) {
continue;
}
$ownItem = $general->getItem($itemType);
if ($ownItem->getRawClassName() == $itemKey) {
$reasons[] = '이미 그 유니크를 가지고 있습니다.';
continue;
}
if (!$ownItem->isBuyable()) {
$reasons[] = '이미 다른 유니크를 가지고 있습니다.';
continue;
}
$availableCnt = $itemList[$itemKey];
$occupiedCnt = $db->queryFirstField('SELECT count(*) FROM general WHERE %b = %s', $itemType, $itemKey);
if ($occupiedCnt >= $availableCnt) {
$reasons[] = '그 유니크는 모두 점유되었습니다.';
continue;
}
$availableItemTypes[] = $itemType;
}
if (!$availableItemTypes) {
rollbackInheritUniqueTrial($general, $itemKey, join(' ', $reasons));
continue;
}
$reasons = [];
$itemType = Util::choiceRandom($availableItemTypes);
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}"); //혹시 itemKey의 크기가 37이 넘을 수 있을까?
$anyTrials = $trialStor->getAll();
if (!$anyTrials) {
//순서가 꼬였던 모양, 실제 값은 storage를 우선시하자
rollbackInheritUniqueTrial($general, $itemKey, '절차상의 오류입니다.');
continue;
}
//XXX: 정렬할 필요 없지 않나?
usort($anyTrials, function ($lhsTrial, $rhsTrial) {
[,, $lhsAmount] = $lhsTrial;
[,, $rhsAmount] = $rhsTrial;
return $rhsAmount <=> $lhsAmount; //큰 값이 앞에 오도록
});
LogText("선택유니크상태 {$ownerID} {$itemKey}", $anyTrials);
//공동 1등인데 본인이 있을 수도 있다.
[,, $topAmount] = $anyTrials[0];
if ($amount < $topAmount) {
$compAmount = $topAmount / $amount;
if ($compAmount > 2.0) {
$compText = '엄청난 차이로 ';
} else if ($compAmount > 1.2) {
$compText = '큰 차이로 ';
} else if ($compAmount > 1.05) {
$compText = '';
} else {
$compText = '아슬아슬한 차이로 ';
}
rollbackInheritUniqueTrial($general, $itemKey, "{$compText}상위 입찰한 장수가 있습니다.");
continue;
}
//내가 1위다
if ($ownTarget !== null) {
//이미 다른 아이템을 얻기로 되어있다.
continue;
}
$ownTarget = $itemKey;
$ownType = $itemType;
}
unset($itemKey);
unset($itemType);
if ($ownTarget === null) {
return false;
}
if ($justRollback) {
return false;
}
LogText("선택유니크획득{$ownerID}", $ownTarget);
$trialStor = KVStorage::getStorage($db, "ut_{$ownTarget}");
$trialStor->deleteValue("u{$ownerID}");
//rollbackInheritUniqueTrial 과정 때문에 새로 받아와야함
$itemTrials = $general->getAuxVar('inheritUniqueTrial');
unset($itemTrials[$ownTarget]);
$general->setAuxVar('inheritUniqueTrial', $itemTrials);
$nationName = $general->getStaticNation()['name'];
$generalName = $general->getName();
$josaYi = JosaUtil::pick($generalName, '이');
$itemObj = buildItemClass($ownTarget);
$itemName = $itemObj->getName();
$itemRawName = $itemObj->getRawName();
$josaUl = JosaUtil::pick($itemRawName, '을');
$general->setVar($ownType, $ownTarget);
$logger = $general->getLogger();
$logger->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 습득했습니다!");
$logger->pushGeneralHistoryLog("<C>{$itemName}</>{$josaUl} 습득");
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
$logger->pushGlobalHistoryLog("<C><b>【{$acquireType}】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 습득했습니다!");
$general->applyDB($db);
//같은 종류의 유니크를 입찰했을 수 있으니 한번 더 검사한다.
tryRollbackInheritUniqueItem($general);
return true;
}
function tryUniqueItemLottery(General $general, string $acquireType = '아이템'): bool
function tryUniqueItemLottery(RandUtil $rng, General $general, string $acquireType = '아이템'): bool
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -1915,18 +1653,9 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
$userLogger = new UserLogger($general->getVar('owner'));
$userLogger->push(sprintf("유니크를 얻을 공간이 없어 %d 포인트 반환", GameConst::$inheritItemRandomPoint), "inheritPoint");
}
tryRollbackInheritUniqueItem($general);
return false;
}
$inheritUnique = $general->getAuxVar('inheritUniqueTrial');
if ($acquireType != '설문조사' && $inheritUnique && count($inheritUnique) && $availableBuyUnique) {
$trialResult = tryInheritUniqueItem($general, $acquireType);
if ($trialResult) {
return true;
}
}
$scenario = $gameStor->scenario;
$genCount = $db->queryFirstField('SELECT count(*) FROM general WHERE npc<2');
@@ -1940,11 +1669,10 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
$prob = 1 / ($genCount * $itemTypeCnt * 0.7 / 3); // 투표율 70%, 설문조사 한번에 2~3개 등장
} else if ($acquireType == '랜덤 임관') {
$prob = 1 / ($genCount * $itemTypeCnt / 10 / 2); // 랜임시 2개(10%) 등장(200명중 20명 랜임시도?)
} else if ($acquireType == '건국') {
$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);
@@ -1954,9 +1682,12 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
//포인트로 랜덤 유니크 획득
$prob = 1;
}
else if ($acquireType == '건국') {
$prob = 1; // 건국시 100%
}
foreach (Util::range($maxCnt) as $_idx) {
if (Util::randBool($prob)) {
if ($rng->nextBool($prob)) {
$result = true;
break;
}
@@ -1968,7 +1699,7 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
}
LogText("{$general->getName()}, {$general->getID()} 유니크 성공 {$maxCnt}", $prob);
return giveRandomUniqueItem($general, $acquireType);
return giveRandomUniqueItem($rng, $general, $acquireType);
}
function getAdmin()
@@ -1998,22 +1729,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, '이');
@@ -2022,13 +1752,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);
@@ -2085,13 +1818,31 @@ function nextRuler(General $general)
//npc or npc유저인 경우 후계 찾기
if (!$fiction && $general->getNPCType() > 0) {
$candidate = $db->queryFirstRow(
'SELECT no,name,officer_level,IF(ABS(affinity-%i)>75,150-ABS(affinity-%i),ABS(affinity-%i)) as npcmatch2 from general where nation=%i and officer_level!=12 and 1 <= npc and npc<=3 order by npcmatch2,rand() LIMIT 1',
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'NextNPCRuler',
$year,
$month,
$general->getID(),
)));
$rawCandidates = $db->query(
'SELECT no,name,officer_level,IF(ABS(affinity-%i)>75,150-ABS(affinity-%i),ABS(affinity-%i)) as npcmatch2 from general where nation=%i and officer_level!=12 and 1 <= npc and npc<=3 order by npcmatch2 asc',
$general->getVar('affinity'),
$general->getVar('affinity'),
$general->getVar('affinity'),
$nationID
);
if ($rawCandidates) {
$candidates = [];
$minNPCMatch = $rawCandidates[0]['npcmatch2'];
foreach ($rawCandidates as $candidate) {
if (!$candidate['npcmatch2'] == $minNPCMatch) {
break;
}
$candidates[] = $candidate;
}
$candidate = $rng->choice($candidates);
}
}
if (!$candidate) {
$candidate = $db->queryFirstRow(
@@ -2415,7 +2166,7 @@ function isNeighbor(int $nation1, int $nation2, bool $includeNoSupply = true)
return false;
}
function SabotageInjury(array $cityGeneralList, string $reason): int
function SabotageInjury(RandUtil $rng, array $cityGeneralList, string $reason): int
{
$injuryCount = 0;
$josaRo = JosaUtil::pick($reason, '로');
@@ -2427,12 +2178,12 @@ function SabotageInjury(array $cityGeneralList, string $reason): int
/** @var General $general */
$injuryProb = 0.3;
$injuryProb = $general->onCalcStat($general, 'injuryProb', $injuryProb);
if (!Util::randBool($injuryProb)) {
if (!$rng->nextBool($injuryProb)) {
continue;
}
$general->getLogger()->pushGeneralActionLog($text);
$general->increaseVarWithLimit('injury', Util::randRangeInt(1, 16), 0, 80);
$general->increaseVarWithLimit('injury', $rng->nextRangeInt(1, 16), 0, 80);
$general->multiplyVar('crew', 0.98);
$general->multiplyVar('atmos', 0.98);
$general->multiplyVar('train', 0.98);
@@ -2445,7 +2196,7 @@ function SabotageInjury(array $cityGeneralList, string $reason): int
return $injuryCount;
}
function getRandTurn($term, ?\DateTimeInterface $baseDateTime = null)
function getRandTurn(RandUtil $rng, $term, ?\DateTimeInterface $baseDateTime = null)
{
if ($baseDateTime === null) {
$baseDateTime = new \DateTimeImmutable();
@@ -2457,13 +2208,13 @@ function getRandTurn($term, ?\DateTimeInterface $baseDateTime = null)
throw new MustNotBeReachedException();
}
$randSecond = Util::randRangeInt(0, 60 * $term - 1);
$randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수
$randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
$randFraction = $rng->nextRangeInt(0, 999999) / 1000000; //6자리 소수
return TimeUtil::format($baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction)), true);
}
function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null)
function getRandTurn2(RandUtil $rng, $term, ?\DateTimeInterface $baseDateTime = null)
{
if ($baseDateTime === null) {
$baseDateTime = new \DateTimeImmutable();
@@ -2472,8 +2223,8 @@ function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null)
} else {
throw new MustNotBeReachedException();
}
$randSecond = Util::randRangeInt(0, 60 * $term - 1);
$randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수
$randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
$randFraction = $rng->nextRangeInt(0, 999999) / 1000000; //6자리 소수
return $baseDateTime->sub(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s.u');
}
+55 -212
View File
@@ -1,247 +1,90 @@
<?php
namespace sammo;
function registerAuction() {
use sammo\Enums\AuctionType;
function registerAuction(RandUtil $rng)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['startyear', 'year', 'month', 'turnterm']);
$unit = 60 * $admin['turnterm'];
// 장수들 평금,평쌀
$general = $db->queryFirstRow('SELECT avg(gold) as gold, avg(rice) as rice,max(gold) as maxgold from general where npc<2');
[$avgGold, $avgRice] = $db->queryFirstList('SELECT avg(gold), avg(rice) from general where npc<2');
$avgGold = Util::valueFit($avgGold, 1000, 20000);
$avgRice = Util::valueFit($avgRice, 1000, 20000);
if($general['gold'] < 1000) { $general['gold'] = 1000; }
if($general['gold'] > 20000) { $general['gold'] = 20000; }
if($general['rice'] < 1000) { $general['rice'] = 1000; }
if($general['rice'] > 20000) { $general['rice'] = 20000; }
$neutralAuctionCnt = Util::convertPairArrayToDict($db->queryAllLists(
'SELECT `type`, count(*) FROM ng_auction WHERE `type` IN %ls AND `host_general_id`=0 GROUP BY `type`',
[AuctionType::BuyRice->value, AuctionType::SellRice->value],
));
$neutralbuyRiceCnt = $neutralAuctionCnt[AuctionType::BuyRice->value] ?? 0;
$count = $db->queryFirstField('SELECT count(*) FROM auction WHERE type=0 AND no1=0');
$count += 5;
// 판매건 등록
if(Util::randBool(1/$count)) {
if ($rng->nextBool(1 / ($neutralbuyRiceCnt + 5))) {
//평균 쌀의 5% ~ 25%
$mul = rand() % 5 + 1;
$amount = $general['rice'] / 20 * $mul;
$cost = $general['gold'] / 20 * 0.9 * $mul;
$mul = $rng->nextRangeInt(1, 5);
$amount = $avgRice / 20 * $mul;
$cost = $avgGold / 20 * 0.9 * $mul;
$topv = $amount * 2;
if($cost <= $amount*0.8) { $cost = $amount*0.8; }
if($cost >= $amount*1.2) { $cost = $amount*1.2; }
$cost = Util::valueFit($cost, $amount * 0.8, $amount * 1.2);
$amount = Util::round($amount, -1);
$cost = Util::round($cost, -1);
$topv = Util::round($topv, -1);
$term = 3 + rand() % 10;
$date = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s")) + $unit * $term);
$db->insert('auction', [
'type'=>0,
'no1'=>0,
'name1'=>'ⓝ상인',
'amount'=>$amount,
'cost'=>$cost,
'value'=>$cost,
'topv'=>$topv,
'expire'=>$date
]);
$term = $rng->nextRangeInt(3, 12);
$dummyGeneral = AuctionBasicResource::genDummy();
AuctionBuyRice::openResourceAuction($dummyGeneral, $amount, $term, $cost, $topv);
}
$count = $db->queryFirstField('SELECT count(*) FROM auction WHERE type=1 AND no1=0');
$count += 5;
$neutralSellRiceCnt = $neutralAuctionCnt[AuctionType::SellRice->value] ?? 0;
// 구매건 등록
if(Util::randBool(1/$count)) {
if ($rng->nextBool(1 / ($neutralSellRiceCnt + 5))) {
//평균 쌀의 5% ~ 25%
$mul = Util::randRangeInt(1, 5);
$amount = $general['rice'] / 20 * $mul;
$cost = $general['gold'] / 20 * 1.1 * $mul;
$topv = $amount * 0.5;
if($cost <= $amount*0.8) { $cost = $amount*0.8; }
if($cost >= $amount*1.2) { $cost = $amount*1.2; }
$mul = $rng->nextRangeInt(1, 5);
$amount = $avgGold / 20 * $mul;
$cost = $avgRice / 20 * 1.1 * $mul;
$topv = $amount * 2;
$cost = Util::valueFit($cost, $amount * 0.8, $amount * 1.2);
$amount = Util::round($amount, -1);
$cost = Util::round($cost, -1);
$topv = Util::round($topv, -1);
$term = Util::randRangeInt(3, 12);
$date = date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s")) + $unit * $term);
$db->insert('auction', [
'type'=>1,
'no1'=>0,
'name1'=>'ⓝ상인',
'amount'=>$amount,
'cost'=>$cost,
'value'=>$cost,
'topv'=>$topv,
'expire'=>$date
]);
$term = $rng->nextRangeInt(3, 12);
$dummyGeneral = AuctionBasicResource::genDummy();
AuctionSellRice::openResourceAuction($dummyGeneral, $amount, $term, $cost, $topv);
}
}
function processAuction() {
function processAuction()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$date = TimeUtil::now();
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$now = TimeUtil::now();
$admin = $gameStor->getValues(['year', 'month']);
$auctionList = $db->queryAllLists(
'SELECT id, `type` FROM ng_auction WHERE `close_date` <= %s AND finished = 0',
$now
);
foreach($db->query('SELECT * from auction where expire<=%s', $date) as $auction){
$josaYi1 = JosaUtil::pick($auction['name1'], '이');
$josaYi2 = JosaUtil::pick($auction['name2'], '이');
// 쌀 처리
if($auction['no2'] == 0) {
// 상인건수가 아닌것만 출력
if($auction['no1'] != 0) {
$traderID = $db->queryFirstField('SELECT no FROM general WHERE no=%i', $auction['no1']);
$logger = new ActionLogger($traderID, 0, $year, $month);
$logger->pushGeneralActionLog("입찰자 부재로 {$auction['no']}번 거래 <M>유찰</>!", ActionLogger::EVENT_PLAIN);
$logger->flush();
$auctionLog = [];
if($auction['type'] == 0) {
$josaUlRice = JosaUtil::pick($auction['amount'], '을');
$auctionLog[] = "<S>◆</>{$admin['year']}{$admin['month']}월, {$auction['no']}번 <span class='sell'>판매</span> <M>유찰</> : <Y>{$auction['name1']}</>{$josaYi1} 쌀 <C>{$auction['amount']}</>{$josaUlRice} 판매, 그러나 입찰자 부재";
} else {
$josaUlRice = JosaUtil::pick($auction['amount'], '을');
$auctionLog[] = "<S>◆</>{$admin['year']}{$admin['month']}월, {$auction['no']}번 <S>구매</> <M>유찰</> : <Y>{$auction['name1']}</>{$josaYi1} 쌀 <C>{$auction['amount']}</>{$josaUlRice} 구매, 그러나 입찰자 부재";
}
pushAuctionLog($auctionLog);
}
continue;
}
if($auction['no1'] == 0) {
$trader = [
'no'=>0,
'name'=>'ⓝ상인',
'gold'=>99999,
'rice'=>99999
];
} else {
$trader = $db->queryFirstRow('SELECT no,name,gold,rice from general where no=%i', $auction['no1']);
}
$bidder = $db->queryFirstRow('SELECT no,name,gold,rice from general where no=%i', $auction['no2']);
$traderLogger = new ActionLogger($trader['no'], 0, $year, $month, false);
$bidderLogger = new ActionLogger($bidder['no'], 0, $year, $month, false);
$auctionLog = [];
//판매거래
if($auction['type'] == 0) {
if($auction['amount'] > $trader['rice'] - 1000) {
$gold = Util::round($auction['value'] * 0.01);
$db->update('general', [
'gold'=>Util::valueFit($trader['gold'] - $gold, 0)
], 'no=%i', $trader['no']);
$josaUlRice = JosaUtil::pick($auction['amount'], '을');
$josaRo = JosaUtil::pick($auction['value'], '로');
$traderLogger->pushGeneralActionLog("판매자의 군량 부족으로 {$auction['no']}번 거래 <M>유찰</>! 벌금 <C>{$gold}</>", ActionLogger::EVENT_PLAIN);
$bidderLogger->pushGeneralActionLog("판매자의 군량 부족으로 {$auction['no']}번 거래 <M>유찰</>!", ActionLogger::EVENT_PLAIN);
$auctionLog[0] = "<S>◆</>{$admin['year']}{$admin['month']}월, {$auction['no']}번 <span class='sell'>판매</span> <M>유찰</> : <Y>{$auction['name1']}</>{$josaYi1} 쌀 <C>{$auction['amount']}</>{$josaUlRice} 판매, <Y>{$auction['name2']}</>{$josaYi2} 금 <C>{$auction['value']}</>{$josaRo} 입찰, 그러나 판매자 군량부족, 벌금 <C>{$gold}</>";
} elseif($auction['value'] > $bidder['gold'] - 1000) {
$gold = Util::round($auction['value'] * 0.01);
$db->update('general', [
'gold'=>Util::valueFit($bidder['gold'] - $gold, 0)
], 'no=%i', $bidder['no']);
$josaUlRice = JosaUtil::pick($auction['amount'], '을');
$josaRo = JosaUtil::pick($auction['value'], '로');
$traderLogger->pushGeneralActionLog("입찰자의 자금 부족으로 {$auction['no']}번 거래 <M>유찰</>!", ActionLogger::EVENT_PLAIN);
$bidderLogger->pushGeneralActionLog("입찰자의 자금 부족으로 {$auction['no']}번 거래 <M>유찰</>! 벌금 <C>{$gold}</>", ActionLogger::EVENT_PLAIN);
$auctionLog[0] = "<S>◆</>{$admin['year']}{$admin['month']}월, {$auction['no']}번 <span class='sell'>판매</span> <M>유찰</> : <Y>{$auction['name1']}</>{$josaYi1} 쌀 <C>{$auction['amount']}</>{$josaUlRice} 판매, <Y>{$auction['name2']}</>{$josaYi2} 금 <C>{$auction['value']}</>{$josaRo} 입찰, 그러나 입찰자 자금부족, 벌금 <C>{$gold}</>";
} else {
$josaUlGold = JosaUtil::pick($auction['value'], '을');
$josaUlRice = JosaUtil::pick($auction['amount'], '을');
$josaRo = JosaUtil::pick($auction['value'], '로');
$traderLogger->pushGeneralActionLog("{$auction['no']}번 거래 <C>성사</>로 쌀 <C>{$auction['amount']}</>{$josaUlRice} 판매, 금 <C>{$auction['value']}</>{$josaUlGold} 획득!", ActionLogger::EVENT_PLAIN);
$bidderLogger->pushGeneralActionLog("{$auction['no']}번 거래 <C>성사</>로 금 <C>{$auction['value']}</>{$josaUlGold} 지불, 쌀 <C>{$auction['amount']}</>{$josaUlRice} 구입!", ActionLogger::EVENT_PLAIN);
$auctionLog[0] = "<S>◆</>{$admin['year']}{$admin['month']}월, {$auction['no']}번 <span class='sell'>판매</span> <C>성사</> : <Y>{$auction['name1']}</>{$josaYi1} 쌀 <C>{$auction['amount']}</>{$josaUlRice} 판매, <Y>{$auction['name2']}</>{$josaYi2} 금 <C>{$auction['value']}</>{$josaRo} 구매";
if($auction['value'] >= $auction['amount'] * 2) {
$auctionLog[0] .= " <R>★ 최고가 거래 ★</>";
} elseif($auction['value'] >= $auction['topv']) {
$auctionLog[0] .= " <M>★ 즉시구매가 거래 ★</>";
} elseif($auction['value'] * 2 <= $auction['amount']) {
$auctionLog[0] .= " <R>★ 최저가 거래 ★</>";
}
$db->update('general', [
'gold'=>$db->sqleval('gold + %i', $auction['value']),
'rice'=>$db->sqleval('rice - %i', $auction['amount']),
], 'no=%i', $auction['no1']);
$db->update('general', [
'gold'=>$db->sqleval('gold - %i', $auction['value']),
'rice'=>$db->sqleval('rice + %i', $auction['amount']),
], 'no=%i', $auction['no2']);
}
pushAuctionLog($auctionLog);
//구매거래
} else {
if($auction['amount'] > $bidder['rice'] - 1000) {
$gold = Util::round($auction['value'] * 0.01);
$db->update('general', [
'gold'=>Util::valueFit($bidder['gold'] - $gold, 0)
], 'no=%i', $bidder['no']);
$josaUlRice = JosaUtil::pick($auction['amount'], '을');
$josaRo = JosaUtil::pick($auction['value'], '로');
$traderLogger->pushGeneralActionLog("입찰자의 군량 부족으로 {$auction['no']}번 거래 <M>유찰</>!", ActionLogger::EVENT_PLAIN);
$bidderLogger->pushGeneralActionLog("입찰자의 군량 부족으로 {$auction['no']}번 거래 <M>유찰</>! 벌금 <C>{$gold}</>", ActionLogger::EVENT_PLAIN);
$auctionLog[0] = "<S>◆</>{$admin['year']}{$admin['month']}월, {$auction['no']}번 <S>구매</> <M>유찰</> : <Y>{$auction['name1']}</>{$josaYi1} 쌀 <C>{$auction['amount']}</>{$josaUlRice} 구매, <Y>{$auction['name2']}</>{$josaYi2} 금 <C>{$auction['value']}</>{$josaRo} 입찰, 그러나 입찰자 군량부족, 벌금 <C>{$gold}</>";
} elseif($auction['value'] > $trader['gold'] - 1000) {
$gold = Util::round($auction['value'] * 0.01);
$db->update('general', [
'gold'=>Util::valueFit($trader['gold'] - $gold, 0)
], 'no=%i', $trader['no']);
$josaUlRice = JosaUtil::pick($auction['amount'], '을');
$josaRo = JosaUtil::pick($auction['value'], '로');
$traderLogger->pushGeneralActionLog("구매자의 자금 부족으로 {$auction['no']}번 거래 <M>유찰</>! 벌금 <C>{$gold}</>", ActionLogger::EVENT_PLAIN);
$bidderLogger->pushGeneralActionLog("구매자의 자금 부족으로 {$auction['no']}번 거래 <M>유찰</>!", ActionLogger::EVENT_PLAIN);
$auctionLog[0] = "<S>◆</>{$admin['year']}{$admin['month']}월, {$auction['no']}번 <S>구매</> <M>유찰</> : <Y>{$auction['name1']}</>{$josaYi1} 쌀 <C>{$auction['amount']}</>{$josaUlRice} 구매, <Y>{$auction['name2']}</>{$josaYi2} 금 <C>{$auction['value']}</>{$josaRo} 입찰, 그러나 구매자 자금부족, 벌금 <C>{$gold}</>";
} else {
$josaUlGold = JosaUtil::pick($auction['value'], '을');
$josaUlRice = JosaUtil::pick($auction['amount'], '을');
$josaRo = JosaUtil::pick($auction['value'], '로');
$traderLogger->pushGeneralActionLog(
"{$auction['no']}번 거래 <C>성사</>로 금 <C>{$auction['value']}</>{$josaUlGold} 지불, 쌀 <C>{$auction['amount']}</>{$josaUlRice} 구입!", ActionLogger::EVENT_PLAIN
);
$bidderLogger->pushGeneralActionLog("{$auction['no']}번 거래 <C>성사</>로 쌀 <C>{$auction['amount']}</>{$josaUlRice} 판매, 금 <C>{$auction['value']}</>{$josaUlGold} 획득!", ActionLogger::EVENT_PLAIN);
$auctionLog[0] = "<S>◆</>{$admin['year']}{$admin['month']}월, {$auction['no']}번 <S>구매</> <C>성사</> : <Y>{$auction['name1']}</>{$josaYi1} 쌀 <C>{$auction['amount']}</>{$josaUlRice} 구매, <Y>{$auction['name2']}</>{$josaYi2} 금 <C>{$auction['value']}</>{$josaRo} 판매";
if($auction['value'] >= $auction['amount'] * 2) {
$auctionLog[0] .= " <R>★ 최고가 거래 ★</>";
} elseif($auction['value'] * 2 <= $auction['amount']) {
$auctionLog[0] .= " <R>★ 최저가 거래 ★</>";
} elseif($auction['value'] <= $auction['topv']) {
$auctionLog[0] .= " <M>★ 즉시구매가 거래 ★</>";
}
$db->update('general', [
'gold'=>$db->sqleval('gold - %i', $auction['value']),
'rice'=>$db->sqleval('rice + %i', $auction['amount']),
], 'no=%i', $auction['no1']);
$db->update('general', [
'gold'=>$db->sqleval('gold + %i', $auction['value']),
'rice'=>$db->sqleval('rice - %i', $auction['amount']),
], 'no=%i', $auction['no2']);
}
$traderLogger->flush();
$bidderLogger->flush();
pushAuctionLog($auctionLog);
}
$traderLogger->flush();
$bidderLogger->flush();
if (!$auctionList) {
return;
}
$db->delete('auction', 'expire <= %s', $date);
$dummyGeneral = AuctionBasicResource::genDummy();
foreach ($auctionList as [$auctionID, $rawAuctionType]) {
$auctionType = AuctionType::from($rawAuctionType);
if ($auctionType === AuctionType::BuyRice) {
$auction = new AuctionBuyRice($auctionID, $dummyGeneral);
} else if ($auctionType === AuctionType::SellRice) {
$auction = new AuctionSellRice($auctionID, $dummyGeneral);
} else if ($auctionType === AuctionType::UniqueItem) {
$auction = new AuctionUniqueItem($auctionID, $dummyGeneral);
} else {
throw new \Exception('Unknown auction type');
}
$auction->tryFinish();
}
}
+20 -5
View File
@@ -3,6 +3,7 @@ namespace sammo;
use sammo\Command\GeneralCommand;
use sammo\Command\NationCommand;
use sammo\Enums\PenaltyKey;
function getGeneralTurnBrief(General $generalObj, array $turnList) {
$result = [];
@@ -213,7 +214,7 @@ function _setGeneralCommand(GeneralCommand $command, array $turnList):void {
$db->update('general_turn', [
'action'=>$commandName,
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'arg'=>Json::encode($arg, Json::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief
], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList);
}
@@ -233,7 +234,7 @@ function _setNationCommand(NationCommand $command, array $turnList):void {
$db->update('nation_turn', [
'action'=>$commandName,
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'arg'=>Json::encode($arg, Json::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief
], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList);
}
@@ -266,7 +267,7 @@ function checkCommandArg(?array $arg):?string{
/*'string'=>[
'nationName', 'optionText', 'itemType', 'nationType', 'commandType',
],*/
'integer'=>[
'int'=>[
'crewType', 'destGeneralID', 'destCityID', 'destNationID',
'amount', 'colorType',
'srcArmType', 'destArmType', //숙련전환 전용
@@ -350,7 +351,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 +426,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 [
@@ -434,6 +435,13 @@ function setNationCommand(int $generalID, array $turnList, string $command, ?arr
];
}
if($general->hasPenalty(PenaltyKey::NoChiefTurnInput)){
return [
'result'=>false,
'reason'=>'수뇌 턴 입력 불가능'
];
}
try{
$commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg);
}
@@ -473,6 +481,13 @@ function setNationCommand(int $generalID, array $turnList, string $command, ?arr
}
_setNationCommand($commandObj, $turnList);
if($general->getNPCType() < 2){
//유저장인 경우에는 턴 리필
$general->updateVarWithLimit('killturn', $env['killturn'], $general->getVar('killturn'));
$general->applyDB($db);
}
return [
'result'=>true,
'brief'=>$commandObj->getBrief(),
+109 -14
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 = '휴식';
@@ -387,6 +457,29 @@ function buildWarUnitTriggerClass(?string $type, WarUnit $unit, ?array $args = n
return $class->newInstanceArgs(array_merge([$unit], $args));
}
function getStaticEventClass(string $type){
static $basePath = __NAMESPACE__.'\\StaticEvent\\';
$classPath = ($basePath.$type);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$type}은 StaticEvent가 아님");
}
function buildStaticEventClass(?string $type):BaseStaticEvent{
static $cache = [];
if(key_exists($type, $cache)){
return $cache[$type];
}
$class = getStaticEventClass($type);
$obj = new $class();
$cache[$type] = $obj;
return $obj;
}
function getGeneralPoolClass(string $type){
static $basePath = __NAMESPACE__.'\\GeneralPool\\';
$classPath = ($basePath.$type);
@@ -405,10 +498,10 @@ function getGeneralPoolClass(string $type){
* @param null|string $prefix
* @return AbsGeneralPool[]
*/
function pickGeneralFromPool(\MeekroDB $db, int $owner, int $pickCnt, ?string $prefix=null):array{
function pickGeneralFromPool(\MeekroDB $db, RandUtil $rng, int $owner, int $pickCnt, ?string $prefix=null):array{
/** @var AbsGeneralPool */
$class = getGeneralPoolClass(GameConst::$targetGeneralPool);
return $class::pickGeneralFromPool($db, $owner, $pickCnt, $prefix);
return $class::pickGeneralFromPool($db, $rng, $owner, $pickCnt, $prefix);
}
function countPureGeneralFromRawList(?array $rawGeneralList=null):int{
@@ -542,6 +635,8 @@ function getExpLevel($experience) {
$level = Util::toInt(sqrt($experience/10));
}
$level = Util::clamp($level, 0, GameConst::$maxLevel);
return $level;
}
+105 -323
View File
@@ -2,7 +2,9 @@
namespace sammo;
use Monolog\Logger;
use sammo\DTO\AuctionInfo;
use sammo\Enums\AuctionType;
use sammo\Enums\EventTarget;
use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn;
@@ -183,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()
{
@@ -219,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, 세율동기화
@@ -284,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
@@ -334,7 +257,7 @@ EOD),
}
// 외교 로그처리, 외교 상태 처리
function postUpdateMonthly()
function postUpdateMonthly(RandUtil $rng)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -380,7 +303,6 @@ function postUpdateMonthly()
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
@@ -397,7 +319,7 @@ function postUpdateMonthly()
//약간의 랜덤치 부여 (95% ~ 105%)
$nation['power'] = Util::round($nation['power'] * (rand() % 101 + 950) / 1000);
$nation['power'] = Util::round($nation['power'] * $rng->nextRange(0.95, 1.05));
$powerValues['maxPower'] = max($powerValues['maxPower'] ?? 0, $nation['power']);
$powerValues['maxCrew'] = max($powerValues['maxCrew'] ?? 0, Util::toInt($nation['totalCrew']));
@@ -450,7 +372,7 @@ function postUpdateMonthly()
continue;
}
//양측 기간 모두 0이 되는 상황이면
//양측 기간 모두 0이 되는 상황이면
$nation1 = getNationStaticInfo($me);
$name1 = $nation1['name'];
$nation2 = getNationStaticInfo($you);
@@ -459,7 +381,7 @@ function postUpdateMonthly()
$josaWa = JosaUtil::pick($name1, '와');
$josaYi = JosaUtil::pick($name2, '이');
$globalLogger->pushGlobalHistoryLog("<R><b>【전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>전</>합니다.");
$globalLogger->pushGlobalHistoryLog("<R><b>【전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>전</>합니다.");
$db->update('diplomacy', [
'state' => 2,
'term' => 0,
@@ -486,12 +408,12 @@ function postUpdateMonthly()
$availableWarSettingCnt = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'available_war_setting_cnt');
foreach ($nations as $nation) {
$nationID = $nation['nation'];
if(!key_exists($nationID, $availableWarSettingCnt)){
if (!key_exists($nationID, $availableWarSettingCnt)) {
$availableWarSettingCnt[$nationID] = 0;
}
}
foreach($availableWarSettingCnt as $nationID=>$cnt){
if($cnt >= GameConst::$maxAvailableWarSettingCnt){
foreach ($availableWarSettingCnt as $nationID => $cnt) {
if ($cnt >= GameConst::$maxAvailableWarSettingCnt) {
continue;
}
$cnt = Util::valueFit($cnt + GameConst::$incAvailableWarSettingCnt, 0, GameConst::$maxAvailableWarSettingCnt);
@@ -500,18 +422,16 @@ function postUpdateMonthly()
//초반이후 방랑군 자동 해체
if ($admin['year'] >= $admin['startyear'] + 2) {
checkWander();
checkWander($rng);
}
// 작위 업데이트
updateNationState();
updateGeneralNumber();
refreshNationStaticInfo();
// 천통여부 검사
checkEmperior();
//토너먼트 개시
triggerTournament();
triggerTournament($rng);
// 시스템 거래건 등록
registerAuction();
registerAuction($rng);
//전방설정
foreach (getAllNationStaticInfo() as $nation) {
if ($nation['level'] <= 0) {
@@ -522,21 +442,21 @@ function postUpdateMonthly()
}
function checkWander()
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();
$logger->pushGeneralActionLog('초반 제한후 방랑군은 자동 해산됩니다.', ActionLogger::PLAIN);
$wanderCmd->run();
$wanderCmd->run($rng);
$wanderCmd->setNextAvailable();
}
}
@@ -546,218 +466,6 @@ function checkWander()
}
}
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']);
$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이 진관수이소중대특 체계를 벗어날 수 있음
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nation['nation']);
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>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['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>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]);
break;
case 5:
case 4:
case 3:
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명됨"]);
break;
case 2:
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['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 = [];
[$startYear, $year] = $gameStor->getValuesAsArray(['startyear', 'year']);
$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];
}
foreach (Util::range($levelDiff) as $idx) {
if (!$uniqueLotteryWeightList) {
break;
}
/** @var General */
$winnerObj = Util::choiceRandomUsingWeightPair($uniqueLotteryWeightList);
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
giveRandomUniqueItem($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;
while ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID += 1;
$npcObj = new Scenario\GeneralBuilder(
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();
@@ -990,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;
}
@@ -1024,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) {
@@ -1033,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);
@@ -1053,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'
@@ -1106,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']);
@@ -1180,15 +899,44 @@ function checkEmperior()
'tiger' => $tigerstr,
'eagle' => $eaglestr,
'gen' => $gen,
'history' => JSON::encode($nationHistory),
'history' => Json::encode($nationHistory),
'aux' => $statGeneral['aux']
]);
$history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."];
$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>"];
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)
@@ -1202,3 +950,37 @@ function updateMaxDomesticCritical(General $general, $score)
$general->setInheritancePoint(InheritanceKey::max_domestic_critical, $maxDomesticCritical);
}
}
function genGenericUniqueRNG(int $year, int $month, int $generalID, ?string $reason = null): RandUtil
{
if($reason){
return new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'unique',
$year,
$month,
$generalID,
$reason
)));
}
return new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'unique',
$year,
$month,
$generalID
)));
}
function genGenericUniqueRNGFromGeneral(General $general, string $reason): RandUtil
{
$logger = $general->getLogger();
if (!$logger) {
throw new \Exception('정식 초기화된 객체가 아닙니다.');
}
$year = $logger->getYear();
$month = $logger->getMonth();
$generalID = $general->getID();
return genGenericUniqueRNG($year, $month, $generalID, $reason);
}
+12 -2
View File
@@ -90,8 +90,8 @@ function pushAuctionLog($log) {
pushRawFileLog(__DIR__."/logs/".UniqueConst::$serverID."/_auctionlog.txt", $log);
}
function getAuctionLogRecent(int $count) {
return join('<br>', array_reverse(getFormattedFileLogRecent(__DIR__."/logs/".UniqueConst::$serverID."/_auctionlog.txt", $count, 300)));
function getAuctionLogRecent(int $count): array {
return array_reverse(getRawFileLogRecent(__DIR__."/logs/".UniqueConst::$serverID."/_auctionlog.txt", $count, 300));
}
//DB-based
@@ -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>";
+6 -7
View File
@@ -3,10 +3,10 @@ namespace sammo;
/**
* 내정 커맨드 사용시 성공 확률 계산
*
*
* @param General $general 장수 정보
* @param string $type 내정 커맨드 타입, 'leadership' = 통솔 기반, 'strength' = 무력 기반, 'intel' = 지력 기반
*
*
* @return array 계산된 실패, 성공 확률 ('success' => 성공 확률, 'fail' => 실패 확률)
*/
function CriticalRatioDomestic(General $general, string $type) {
@@ -24,7 +24,7 @@ function CriticalRatioDomestic(General $general, string $type) {
506040(33%/30%), 505050(43%/40%), 504060(50%/50%)
* 통솔 내정 기준
756510(25%/22%), 707010(31%/28%), 657510(38%,35%),
756510(25%/22%), 707010(31%/28%), 657510(38%,35%),
505050(50%,50%), 107070(50%,50%)
*/
switch($type) {
@@ -60,13 +60,12 @@ function calcLeadershipBonus($officerLevel, $nationLevel):int{
return $lbonus;
}
function CriticalScoreEx(string $type):float {
function CriticalScoreEx(RandUtil $rng, string $type):float {
if ($type == 'success') {
return Util::randRange(2.2, 3.0);
return $rng->nextRange(2.2, 3.0);
}
if ($type == 'fail') {
return Util::randRange(0.2, 0.4);
return $rng->nextRange(0.2, 0.4);
}
return 1;
}
+5 -60
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') ?>
@@ -60,7 +61,8 @@ function chiefTurnTable()
";
}
function templateLimitMsg(string $turntime): string{
function templateLimitMsg(string $turntime): string
{
return "이미 너무 많은 접속을 하셨습니다. 다음 턴에 다시 시도해주세요. (턴시간: {$turntime})";
}
@@ -129,7 +131,7 @@ function allButton(bool $seizeNPCMode, array $opts = [])
$site = "a_npcList.php";
$call = "빙의일람";
} else {
$site = "a_vote.php";
$site = "v_vote.php";
$call = "설문조사";
}
@@ -146,63 +148,6 @@ function allButton(bool $seizeNPCMode, array $opts = [])
], $opts));
}
function commandButton(array $opts = [])
{
$session = Session::getInstance();
$userID = Session::getUserID();
if (!$session->isGameLoggedIn()) {
return '';
}
$db = DB::db();
$me = $db->queryFirstRow("select no,nation,officer_level,belong,permission,penalty from general where owner=%i", $userID);
$nation = $db->queryFirstRow("select nation,level,color,secretlimit from nation where nation=%i", $me['nation']) ?? [
'nation' => 0,
'level' => 0,
'secretlimit' => 99,
'color' => '#000000'
];
$bgColor = Util::array_get($nation['color']) ?: '#000000';
$fgColor = newColor($bgColor);
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
$showSecret = false;
$permission = checkSecretPermission($me);
$btnClassForTournament = $opts['btnClass'];
if ($opts['isTournamentApplicationOpen']) {
if ($btnClassForTournament != 'dropdown-item') {
$btnClassForTournament = 'toolbarButton2';
}
}
$btnClassForBetting = $opts['btnClass'];
if ($opts['isBettingActive']) {
if ($btnClassForTournament != 'dropdown-item') {
$btnClassForBetting = 'toolbarButton2';
}
}
if ($permission >= 1) {
$showSecret = true;
} else if ($me['officer_level'] == 0) {
$showSecret = false;
}
return $templates->render('commandButton', array_merge([
'bgColor' => $bgColor,
'fgColor' => $fgColor,
'meLevel' => $me['officer_level'],
'nationLevel' => $nation['level'],
'showSecret' => $showSecret,
'permission' => $permission,
'btnClassForTournament' => $btnClassForTournament,
'btnClassForBetting' => $btnClassForBetting,
], $opts));
}
function formatWounded(int $value, int $wound): string
{
if ($wound == 0) {
@@ -246,7 +191,7 @@ function getMapHtml(?string $mapName = null)
{
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
if($mapName === null){
if ($mapName === null) {
$mapName = GameConst::$mapName;
}
+33 -291
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) {
@@ -513,7 +248,7 @@ function getOutcome(float $billRate, array $generalList) {
return $outcome;
}
function tradeRate() {
function tradeRate(RandUtil $rng) {
$db = DB::db();
foreach($db->query('SELECT city,level FROM city') as $city){
@@ -528,8 +263,8 @@ function tradeRate() {
7=>0.8,
8=>1
][$city['level']];
if($prob > 0 && Util::randBool($prob)) {
$trade = Util::randRangeInt(95, 105);
if($prob > 0 && $rng->nextBool($prob)) {
$trade = $rng->nextRangeInt(95, 105);
} else {
$trade = null;
}
@@ -539,7 +274,7 @@ function tradeRate() {
}
}
function disaster() {
function disaster(RandUtil $rng) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -560,7 +295,7 @@ function disaster() {
10=>0
];
$isGood = Util::randBool($boomingRate[$month]);
$isGood = $rng->nextBool($boomingRate[$month]);
$targetCityList = [];
@@ -575,7 +310,7 @@ function disaster() {
$raiseProp = 0.06 - ($city['secu'] / $city['secu_max']) * 0.05; // 1 ~ 6%
}
if(Util::randBool($raiseProp)) {
if($rng->nextBool($raiseProp)) {
$targetCityList[] = $city;
}
}
@@ -621,7 +356,7 @@ function disaster() {
10 => null
];
[$logTitle, $stateCode, $logBody] = Util::choiceRandom(($isGood?$boomingTextList:$disasterTextList)[$month]);
[$logTitle, $stateCode, $logBody] = $rng->choice(($isGood?$boomingTextList:$disasterTextList)[$month]);
$logger = new ActionLogger(0, 0, $year, $month, false);
@@ -629,7 +364,14 @@ function disaster() {
$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,12 +390,12 @@ function disaster() {
$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']]??[]
);
SabotageInjury($generalList, '재난');
SabotageInjury($rng, $generalList, '재난');
}
}
else{
+37 -81
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;
@@ -383,14 +329,16 @@ function getDummyBettingInfo(string $tnmt_type): BettingInfo
name: $tnmt_type,
finished: true,
selectCnt: 1,
isExclusive: null,
reqInheritancePoint: false,
openYearMonth: 0,
closeYearMonth: 0,
candidates: []
candidates: [],
winner: null,
);
}
function startBetting($type, $unit)
function startBetting($type)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -425,10 +373,10 @@ function startBetting($type, $unit)
$candidates[$general['no']] = new \sammo\DTO\SelectItem(
title: $general['name'],
info: "{$statName}: {$general[$statKey]}",
isHtml: null,
aux: $general
);
}
$candidateCnt = count($candidates);
Betting::openBetting(new BettingInfo(
id: $bettingID,
@@ -436,10 +384,12 @@ function startBetting($type, $unit)
name: $typeText,
finished: false,
selectCnt: 1,
isExclusive: null,
reqInheritancePoint: false,
openYearMonth: $openYearMonth,
closeYearMonth: $closeYearMonth,
candidates: $candidates,
winner: null,
));
$betting = new Betting($bettingID);
@@ -448,12 +398,18 @@ function startBetting($type, $unit)
$betGold = Util::valueFit(floor((3 + $year - $startyear) * 0.334) * 10, 10);
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'OpenBettingTournament',
$bettingID,
)));
$npcList = $db->queryFirstColumn('SELECT no FROM general WHERE npc >= 2 AND gold >= (500 + %i)', $betGold);
$npcBet = [];
$targetList = array_keys($candidates);
foreach ($npcList as $npcID) {
$target = Util::choiceRandom($targetList);
$target = $rng->choice($targetList);
$npcBet[] = [$npcID, $target];
}
@@ -926,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;
@@ -971,7 +927,7 @@ function setGift($tnmt_type, $tnmt, $phase)
}
//자동진행 끝
$gameStor->tnmt_auto = 0;
$gameStor->tnmt_auto = false;
//장수열전 기록
/** @var ActionLogger */
@@ -990,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']);
@@ -1030,7 +986,7 @@ function setRefund()
}
//자동진행 끝
$gameStor->tnmt_auto = 0;
$gameStor->tnmt_auto = false;
}
//10차이 1.1, 50 차이 1.17, 100차이 1.2
+21 -394
View File
@@ -4,415 +4,42 @@ namespace sammo;
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(`no`) FROM auction');
$isTournamentActive = $gameStor->tournament > 0;
$isTournamentApplicationOpen = $gameStor->tournament == 1;
$isBettingActive = $gameStor->tournament == 6;
$myNationStatic = getNationStaticInfo($generalObj->getNationID());
$nationColorType = substr($myNationStatic['color'] ?? '#000000', 1);
$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);
}
?>
<!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
$vote = $gameStor->vote ?: [''];
$vote_title = Tag2Code($gameStor->vote_title ?? '-');
?>
<?php if ($vote[0] == "") : ?>
<span style='color:magenta'>진행중 설문 없음</span>
<?php else : ?>
<span style='color:cyan'>설문 진행중</span> : <span><?= $vote_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(['btnClass' => 'btn btn-sammo-nation', '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>', 'btnClass' => '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,
+9 -2
View File
@@ -110,16 +110,23 @@ foreach($db->queryFirstColumn('SELECT pick_result FROM select_npc_token WHERE `o
}
}
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'SelectNPCToken',
$userID,
$now,
)));
$pickLimit = min(count($candidates), 5);
while(count($pickResult) < $pickLimit){
$generalID = Util::choiceRandomUsingWeight($weight);
$generalID = $rng->choiceUsingWeight($weight);
if(!key_exists($generalID, $pickResult)){
$pickResult[$generalID] = $candidates[$generalID];
}
}
$newNonce = mt_rand(0, 0xfffffff);
$newNonce = random_int(0, 0xfffffff);
$validSecond = max(VALID_SECOND, $turnterm*40);
$pickMoreSecond = max(PICK_MORE_SECOND, Util::round(pow($turnterm, 0.672)*8));
+5 -1
View File
@@ -74,9 +74,13 @@ if($tokens){
]);
}
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed, 'selectPool', $userID, $now
)));
$pick = [];
$valid_until = null;
foreach(pickGeneralFromPool($db, $userID, 14) as $pickObj){
foreach(pickGeneralFromPool($db, $rng, $userID, 14) as $pickObj){
$valid_until = $pickObj->getValidUntil();
$info = $pickObj->getInfo();
putInfoText($info);
+30 -22
View File
@@ -4,8 +4,6 @@ namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly();
if(!class_exists('\\sammo\\DB')){
@@ -111,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 = [];
@@ -144,7 +142,7 @@ $autorun_user = $autorun_user_minutes?[
if($reserve_open){
$reserve_open = new \DateTime($reserve_open);
$db = DB::db();
if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) {
$clearResult = ResetHelper::clearDB();
if(!$clearResult['result']){
@@ -159,7 +157,9 @@ if($reserve_open){
]);
}
$scenarioObj = new Scenario($scenario, true);
$rng = new RandUtil(new LiteHashDRBG(random_bytes(16)));
$scenarioObj = new Scenario($rng, $scenario, true);
$open_date = $reserve_open->format('Y-m-d H:i:s');
$reserveInfo = [
@@ -179,14 +179,14 @@ if($reserve_open){
'autorun_user'=>$autorun_user
];
if($pre_reserve_open){
$pre_reserve_open = new \DateTime($pre_reserve_open);
$open_date = $pre_reserve_open->format('Y-m-d H:i:s');
}
$db->delete('reserved_open', true);
$db->insert('reserved_open', [
'options'=>Json::encode($reserveInfo),
@@ -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()
]);
}
+29 -14
View File
@@ -53,22 +53,17 @@ if($fullReset){
}
}
function dbConnFail($params){
$db = new \MeekroDB($host,$username,$password,$dbName,$port,'utf8mb4');
$db->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$db->addHook('run_failed', function(){
Json::die([
'result'=>false,
'reason'=>'DB 접속에 실패했습니다.'
]);
}
});
$db = new \MeekroDB($host,$username,$password,$dbName,$port,'utf8mb4');
$db->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$db->throw_exception_on_nonsql_error = false;
$db->nonsql_error_handler = 'dbConnFail';
$mysqli_obj = $db->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
$mysqli_obj = $db->get();
$prefix = basename(__DIR__);
@@ -84,8 +79,6 @@ $result = Util::generateFileUsingSimpleTemplate(
], true
);
if($result !== true){
Json::die([
'result'=>false,
@@ -93,7 +86,29 @@ if($result !== true){
]);
}
ResetHelper::clearDB();
//최소한의 테이블 처리를 위해 수동으로 초기화하도록 하자
if($mysqli_obj->multi_query(file_get_contents(__DIR__.'/sql/reset.sql'))){
while(true){
if (!$mysqli_obj->more_results()) {
break;
}
if(!$mysqli_obj->next_result()){
break;
}
}
}
if($mysqli_obj->multi_query(file_get_contents(__DIR__.'/sql/schema.sql'))){
while(true){
if (!$mysqli_obj->more_results()) {
break;
}
if(!$mysqli_obj->next_result()){
break;
}
}
}
ServConfig::getServerList()[$prefix]->closeServer();
+9 -1
View File
@@ -19,7 +19,15 @@ if(!prepareDir('data/file_cache')){
]);
}
$storage = new \Nette\Caching\Storages\FileStorage('data/file_cache');
$absolutePath = realpath('data/file_cache');
if(!$absolutePath){
Json::die([
'result'=>false,
'reason'=>'cache 불가'
]);
}
$storage = new \Nette\Caching\Storages\FileStorage($absolutePath);
$cache = new Cache($storage);
$serverID = UniqueConst::$serverID;
-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
]);
+168 -129
View File
@@ -1,6 +1,13 @@
<?php
namespace sammo;
use sammo\Enums\GeneralColumn;
use sammo\Enums\GeneralLiteQueryMode;
use sammo\Enums\GeneralQueryMode;
use sammo\Enums\MessageType;
use sammo\Enums\PenaltyKey;
include "lib.php";
include "func.php";
@@ -17,97 +24,99 @@ $userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['startyear','year','month','scenario']);
$gameStor->cacheValues(['startyear', 'year', 'month', 'scenario', 'killturn']);
$me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
$me = $db->queryFirstRow('SELECT no,npc,nation,officer_level,penalty from general where owner=%i', $userID);
$myOfficerLevel = $me['officer_level'];
$nationID = $me['nation'];
$myPenalty = Json::decode($me['penalty'] ?? '{}');
//수뇌가 아니면 아무것도 할 수 없음
if($myOfficerLevel < 5){
if ($myOfficerLevel < 5) {
Json::die([
'result'=>false,
'reason'=>'수뇌가 아닙니다.'
'result' => false,
'reason' => '수뇌가 아닙니다.'
]);
}
if($action === '추방' && $destGeneralID==0){
if ($action === '추방' && $destGeneralID == 0) {
Json::die([
'result'=>false,
'reason'=>'장수가 지정되지 않았습니다.'
'result' => false,
'reason' => '장수가 지정되지 않았습니다.'
]);
}
if($destGeneralID==0){
if ($destGeneralID == 0) {
$general = new DummyGeneral(true);
$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);
} else {
$general = General::createObjFromDB($destGeneralID);
if($general instanceof DummyGeneral){
if ($general instanceof DummyGeneral) {
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 장수입니다.'
'result' => false,
'reason' => '올바르지 않은 장수입니다.'
]);
}
if($nationID != $general->getNationID()){
if ($nationID != $general->getNationID()) {
Json::die([
'result'=>false,
'reason'=>'아국 장수가 아닙니다'
'result' => false,
'reason' => '아국 장수가 아닙니다'
]);
}
}
if($officerLevel == 12){
if ($officerLevel == 12) {
Json::die([
'result'=>false,
'reason'=>'군주를 대상으로 할 수 없습니다.'
'result' => false,
'reason' => '군주를 대상으로 할 수 없습니다.'
]);
}
function do수뇌임명(General $general, int $targetOfficerLevel):?string{
function do수뇌임명(General $general, int $targetOfficerLevel): ?string
{
global $myPenalty;
if ($myPenalty[PenaltyKey::NoChiefChange->value] ?? false) {
return '수뇌를 임명할 수 없는 상태입니다.';
}
$generalID = $general->getID();
$nationID = $general->getNationID();
if($general->hasPenalty(PenaltyKey::NoChief)){
return '수뇌가 될 수 없는 상태입니다.';
}
$db = DB::db();
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i',$nationID);
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i', $nationID);
// 임명가능 레벨
// 임명가능 레벨
$lv = getNationChiefLevel($nationLevel);
if($targetOfficerLevel < $lv){
if ($targetOfficerLevel < $lv) {
return '임명불가능한 관직입니다.';
}
if(isOfficerSet($chiefSet, $targetOfficerLevel)){
if (isOfficerSet($chiefSet, $targetOfficerLevel)) {
return '지금은 임명할 수 없습니다.';
}
//기존 장수 일반으로
$db->update('general', [
'officer_level'=>1,
'officer_city'=>0,
'officer_level' => 1,
'officer_city' => 0,
], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID);
if($targetOfficerLevel === 11){
}
else if($targetOfficerLevel % 2 == 0){
if($general->getVar('strength') < GameConst::$chiefStatMin){
if ($targetOfficerLevel === 11) {
} else if ($targetOfficerLevel % 2 == 0) {
if ($general->getVar('strength') < GameConst::$chiefStatMin) {
return '무력이 부족합니다.';
}
}
else{
if($general->getVar('intel') < GameConst::$chiefStatMin){
} else {
if ($general->getVar('intel') < GameConst::$chiefStatMin) {
return '지력이 부족합니다.';
}
}
@@ -116,52 +125,59 @@ function do수뇌임명(General $general, int $targetOfficerLevel):?string{
$general->setVar('officer_level', $targetOfficerLevel);
$general->setVar('officer_city', 0);
$db->update('nation', [
'chief_set'=> $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)),
'chief_set' => $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)),
], 'nation=%i', $nationID);
$general->applyDB($db);
return null;
}
function do도시임명(General $general, int $cityID, int $targetOfficerLevel):?string{
function do도시임명(General $general, int $cityID, int $targetOfficerLevel): ?string
{
global $myPenalty;
$nationID = $general->getNationID();
$db = DB::db();
if(CityConst::byID($cityID) === null){
if (CityConst::byID($cityID) === null) {
return '올바르지 않은 도시입니다';
}
if ($general->getVar(GeneralColumn::officer_level) >= 4 && $myPenalty[PenaltyKey::NoChiefChange->value] ?? false) {
return '수뇌인 장수를 변경할 수 없는 상태입니다.';
}
$officerSet = $db->queryFirstField('SELECT officer_set FROM city WHERE nation=%i AND city=%i', $nationID, $cityID);
if($officerSet === null){
if ($officerSet === null) {
return '아국 도시가 아닙니다';
}
if(isOfficerSet($officerSet, $targetOfficerLevel)){
if (isOfficerSet($officerSet, $targetOfficerLevel)) {
return '이미 다른 장수가 임명되어있습니다';
}
//기존 장수 일반으로
$db->update('general', [
'officer_level'=>1,
'officer_city'=>0,
'officer_level' => 1,
'officer_city' => 0,
], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID());
if($general instanceof DummyGeneral){
if ($general instanceof DummyGeneral) {
return null;
}
if($targetOfficerLevel === 4 && $general->getVar('strength') < GameConst::$chiefStatMin){
if ($targetOfficerLevel === 4 && $general->getVar('strength') < GameConst::$chiefStatMin) {
return '무력이 부족합니다.';
}
if($targetOfficerLevel === 3 && $general->getVar('intel') < GameConst::$chiefStatMin){
if ($targetOfficerLevel === 3 && $general->getVar('intel') < GameConst::$chiefStatMin) {
return '지력이 부족합니다.';
}
//신임 장수
$db->update('city', [
'officer_set'=>$db->sqleval('officer_set | %i', doOfficerSet(0, $targetOfficerLevel)),
'officer_set' => $db->sqleval('officer_set | %i', doOfficerSet(0, $targetOfficerLevel)),
], 'city=%i AND nation=%i', $cityID, $nationID);
$general->setVar('officer_level', $targetOfficerLevel);
$general->setVar('officer_city', $cityID);
@@ -170,22 +186,25 @@ function do도시임명(General $general, int $cityID, int $targetOfficerLevel):
return null;
}
function do추방(General $general, int $myOfficerLevel):?string{
function do추방(General $general, int $myOfficerLevel): ?string
{
$generalID = $general->getID();
$generalName = $general->getVar('name');
$nationID = $general->getNationID();
if ($myPenalty[PenaltyKey::NoBanGeneral->value] ?? false) {
return '추방할 수 없는 상태입니다.';
}
//추방할사람이 외교권자이면 불가
$permission = checkSecretPermission($general->getRaw());
if($permission == 4){
if ($permission == 4) {
return '외교권자는 추방할 수 없습니다.';
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getValues(['startyear','year','month','scenario']);
$env = $gameStor->getValues(['startyear', 'year', 'month', 'scenario']);
$nation = $db->queryFirstRow('SELECT name,chief_set,color FROM nation WHERE nation=%i', $nationID);
$nationName = $nation['name'];
@@ -193,17 +212,17 @@ function do추방(General $general, int $myOfficerLevel):?string{
$logger = $general->getLogger();
//이미 지정했다면 무시
if(isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) {
if (isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) {
return '이미 추방 권한을 사용했습니다.';
}
$gold = 0;
$rice = 0;
// 금쌀1000이상은 남김
if($general->getVar('gold') > GameConst::$defaultGold) {
if ($general->getVar('gold') > GameConst::$defaultGold) {
$gold = $general->getVar('gold') - GameConst::$defaultGold;
$general->setVar('gold', GameConst::$defaultGold);
}
if($general->getVar('rice') > GameConst::$defaultRice) {
if ($general->getVar('rice') > GameConst::$defaultRice) {
$rice = $general->getVar('rice') - GameConst::$defaultRice;
$general->setVar('rice', GameConst::$defaultRice);
}
@@ -221,74 +240,82 @@ function do추방(General $general, int $myOfficerLevel):?string{
$logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.", ActionLogger::PLAIN);
// 명성/공헌 N*10%감소
if($env['year'] <= $env['startyear'] && $general->getNPCType() < 2){
if ($env['year'] <= $env['startyear'] && $general->getNPCType() < 2) {
$general->setVar('makelimit', $oldMakeLimit);
}
else{
} 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);
}
//부대장일 경우
if($general->getVar('troop') == $generalID){
if ($general->getVar('troop') == $generalID) {
// 모두 탈퇴
$db->update('general', [
'troop'=>0,
'troop' => 0,
], 'troop = %i', $generalID);
$db->delete('troop', 'troop_leader=%i', $generalID);
}
$general->setVar('troop', 0);
if($general->getNPCType() >= 2 && Util::randBool(GameConst::$npcBanMessageProb)) {
if ($general->getNPCType() >= 2) {
$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'BanNPC',
$env['year'],
$env['month'],
$general->getID(),
)));
if ($rng->nextBool(GameConst::$npcBanMessageProb)) {
$str = Util::choiceRandom([
'날 버리다니... 곧 전장에서 복수해주겠다...',
'추방이라... 내가 무얼 잘못했단 말인가...',
'어디 추방해가면서 잘되나 보자... 꼭 복수하겠다...',
'인덕이 제일이거늘... 추방이 웬말인가... 저주한다!',
'날 추방했으니 그 복수로 적국에 정보를 팔아 넘겨야겠군요. 그럼 이만.'
]);
$str = $rng->choice([
'날 버리다니... 곧 전장에서 복수해주겠다...',
'추방이라... 내가 무얼 잘못했단 말인가...',
'어디 추방해가면서 잘되나 보자... 꼭 복수하겠다...',
'인덕이 제일이거늘... 추방이 웬말인가... 저주한다!',
'날 추방했으니 그 복수로 적국에 정보를 팔아 넘겨야겠군요. 그럼 이만.'
]);
$src = new MessageTarget(
$generalID,
$generalName,
$nationID,
$nation['name'],
$nation['color'],
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
);
$msg = new Message(
Message::MSGTYPE_PUBLIC,
$src,
$src,
$str,
new \DateTime(),
new \DateTime('9999-12-31'),
[]
);
$msg->send();
$src = new MessageTarget(
$generalID,
$generalName,
$nationID,
$nation['name'],
$nation['color'],
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
);
$msg = new Message(
MessageType::public,
$src,
$src,
$str,
new \DateTime(),
new \DateTime('9999-12-31'),
[]
);
$msg->send();
}
}
if($env['year'] < $env['startyear']+3) {
if ($env['year'] < $env['startyear'] + 3) {
//초반엔 군주 부상 증가(엔장 임관지양)
$db->update('general', [
'injury'=>$db->sqleval('least(injury + 1, %i)', 80),
'injury' => $db->sqleval('least(injury + 1, %i)', 80),
], 'nation=%i AND officer_level=12', $nationID);
$db->update('nation', [
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
'gold'=>$db->sqleval('gold + %i', $gold),
'rice'=>$db->sqleval('rice + %i', $rice),
'gennum' => $db->sqleval('gennum - %i', $general->getNPCType() != 5 ? 1 : 0),
'gold' => $db->sqleval('gold + %i', $gold),
'rice' => $db->sqleval('rice + %i', $rice),
], 'nation = %i', $nationID);
} else {
//이번분기는 추방불가(초반 제외)
$db->update('nation', [
'chief_set'=>$db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)),
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
'gold'=>$db->sqleval('gold + %i', $gold),
'rice'=>$db->sqleval('rice + %i', $rice),
'chief_set' => $db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)),
'gennum' => $db->sqleval('gennum - %i', $general->getNPCType() != 5 ? 1 : 0),
'gold' => $db->sqleval('gold + %i', $gold),
'rice' => $db->sqleval('rice + %i', $rice),
], 'nation = %i', $nationID);
}
@@ -300,62 +327,74 @@ function do추방(General $general, int $myOfficerLevel):?string{
if($action == "임명") {
if(2 <= $officerLevel && $officerLevel <= 4){
if(!$destCityID){
if ($action == "임명") {
if (2 <= $officerLevel && $officerLevel <= 4) {
if (!$destCityID) {
Json::die([
'result'=>false,
'reason'=>'도시가 지정되지 않았습니다.'
'result' => false,
'reason' => '도시가 지정되지 않았습니다.'
]);
}
$result = do도시임명($general, $destCityID, $officerLevel);
if($result !== null){
if ($result !== null) {
Json::die([
'result'=>false,
'reason'=>$result
'result' => false,
'reason' => $result
]);
}
//수뇌의 삭턴 리필
$db->update('general', [
'killturn' => $db->sqleval('GREATEST(%b, %i)', 'killturn', $gameStor->getValue('killturn')),
], 'no=%i', $me['no']);
Json::die([
'result'=>true,
'reason'=>'success'
'result' => true,
'reason' => 'success'
]);
}
if(5 <= $officerLevel && $officerLevel < 12){
if (5 <= $officerLevel && $officerLevel < 12) {
$result = do수뇌임명($general, $officerLevel);
if($result !== null){
if ($result !== null) {
Json::die([
'result'=>false,
'reason'=>$result
'result' => false,
'reason' => $result
]);
}
//수뇌의 삭턴 리필
$db->update('general', [
'killturn' => $db->sqleval('GREATEST(%b, %i)', 'killturn', $gameStor->getValue('killturn')),
], 'no=%i', $me['no']);
Json::die([
'result'=>true,
'reason'=>'success'
'result' => true,
'reason' => 'success'
]);
}
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 지정입니다.'
'result' => false,
'reason' => '올바르지 않은 지정입니다.'
]);
}
if($action == "추방") {
if ($action == "추방") {
$result = do추방($general, $myOfficerLevel);
if($result !== null){
if ($result !== null) {
Json::die([
'result'=>false,
'reason'=>$result
'result' => false,
'reason' => $result
]);
}
//수뇌의 삭턴 리필
$db->update('general', [
'killturn' => $db->sqleval('GREATEST(%b, %i)', 'killturn', $gameStor->getValue('killturn')),
], 'no=%i', $me['no']);
Json::die([
'result'=>true,
'reason'=>'success'
'result' => true,
'reason' => 'success'
]);
}
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 명령입니다.'
]);
'result' => false,
'reason' => '올바르지 않은 명령입니다.'
]);
+22 -3
View File
@@ -1,6 +1,8 @@
<?php
namespace sammo;
use sammo\Enums\GeneralAccessLogColumn;
include "lib.php";
include "func.php";
@@ -25,14 +27,25 @@ $rootDB = RootDB::db();
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
$userNick = RootDB::db()->queryFirstField('SELECT `NAME` FROM member WHERE `NO`=%i',$userID);
if(!$userNick){
$member = $rootDB->queryFirstRow('SELECT `name`, `penalty` FROM member WHERE `NO`=%i', $userID);
if(!$member){
Json::die([
'result'=>false,
'reason'=>'멤버 정보를 가져오지 못했습니다.'
]);
}
$userNick = $member['name'];
$memberPenalty = Json::decode($member['penalty'] ?? '{}');
$penaltyInfo = array_merge($memberPenalty['any'] ?? [], $memberPenalty[DB::prefix()] ?? []);
$penalty = [];
foreach($penaltyInfo as $penaltyKey => $penaltyValue){
if($penaltyValue['expire'] ?? 0 > TimeUtil::now()){
$penalty[$penaltyKey] = $penaltyValue['value'];
}
}
$pickResult = $db->queryFirstField('SELECT pick_result FROM select_npc_token WHERE `owner`=%i AND `valid_until`>=%s', $userID, $now);
if(!$pickResult){
Json::die([
@@ -84,8 +97,14 @@ $db->update('general', [
'defence_train'=>80,
'permission'=>'normal',
'owner'=>$userID,
'aux'=>Json::encode($genAux)
'aux'=>Json::encode($genAux),
'penalty'=>Json::encode($penalty),
], '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([
+1 -1
View File
@@ -103,7 +103,7 @@ foreach(GameConst::$generalPoolAllowOption as $allowOption){
}
else if($allowOption == 'ego'){
if(!$personal || $personal == 'Random'){
$personal = Util::choiceRandom(GameConst::$availablePersonality);
$personal = Util::choiceRandom(GameConst::$availablePersonality);
}
if(!array_search($personal, GameConst::$availablePersonality)){
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']?'가상':'사실';
+44 -18
View File
@@ -1,4 +1,5 @@
<?php
namespace sammo;
include "lib.php";
@@ -24,29 +25,31 @@ if ($defence_train <= 40) {
$defence_train = 40;
}
if($defence_train <= 90){
if ($defence_train <= 90) {
$defence_train = Util::round($defence_train, -1);
}
else{
} else {
$defence_train = 999;
}
if($tnmt < 0 || $tnmt > 1){
if ($tnmt < 0 || $tnmt > 1) {
$tnmt = 1;
}
$db = DB::db();
$me = General::createGeneralObjFromDB($generalID);
$me = General::createObjFromDB($generalID);
if($defence_train !== $me->getVar('defence_train')){
if($defence_train == 999){
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);
}
else{
$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);
$me->setVar('defence_train', $defence_train);
}
@@ -56,21 +59,44 @@ $me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100));
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
$me->setVar('tnmt', $tnmt);
if($me->getNPCType() == 1 && $detachNPC){
if ($me->getNPCType() == 1 && $detachNPC) {
$turnterm = $gameStor->turnterm;
if($turnterm < 10){
if ($turnterm < 10) {
$targetKillTurn = 30 / $turnterm;
}
else{
} else {
$targetKillTurn = 60 / $turnterm;
}
$me->setVar('killturn', $targetKillTurn);
}
$rootDB = RootDB::db();
//회원 테이블에서 정보확인
$member = $rootDB->queryFirstRow('SELECT `no`, id, picture, grade, `name`, imgsvr, `penalty` FROM member WHERE no=%i', $userID);
if (!$member) {
//이런 경우가 있나?
//TODO: 로그 남겨둘 것
Json::die([
'result' => false,
'reason' => '회원 정보를 찾을 수 없습니다.'
]);
}
$memberPenalty = Json::decode($member['penalty'] ?? "{}");
$penaltyInfo = array_merge($memberPenalty['any'] ?? [], $memberPenalty[DB::prefix()] ?? []);
$penalty = [];
foreach ($penaltyInfo as $penaltyKey => $penaltyValue) {
if ($penaltyValue['expire'] ?? 0 > TimeUtil::now()) {
$penalty[$penaltyKey] = $penaltyValue['value'];
}
}
$me->setVar('penalty', Json::encode($penalty));
$me->applyDB($db);
Json::die([
'result'=>true,
'reason'=>'success'
]);
'result' => true,
'reason' => 'success'
]);
+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}의 입력양식이 올바르지 않습니다.";

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