Compare commits

...
201 Commits
Author SHA1 Message Date
Hide_D 798ab3e183 암행부 병종 표기 버그 수정 2018-08-21 02:24:58 +09:00
Hide_D 5508aa4533 전투 엔진 버그 4차 수정 2018-08-21 02:22:29 +09:00
Hide_D 81b7ebbab6 전투 엔진 버그 3차 수정 2018-08-21 02:01:56 +09:00
Hide_D 2d06e33e10 운영자가 '지도'에서 도시를 클릭할 수 있도록 변경 2018-08-21 01:32:00 +09:00
Hide_D d8cc820572 전투 엔진 버그 2차 수정 2018-08-21 01:22:18 +09:00
Hide_D d0ca46cfde 전투 엔진 버그 1차 수정 2018-08-21 00:53:00 +09:00
Hide_D 513124161e 전투 종료 코드 구현(마무리?) 2018-08-20 23:57:36 +09:00
Hide_D 7cfd8c7f79 전투 종료 코드 구현(마무리?) 2018-08-20 22:26:34 +09:00
Hide_D c32ce5e795 전투 종료 코드 구현 2018-08-20 22:20:59 +09:00
Hide_D d9c1530651 일부 게임 유틸리티 함수 간소화 2018-08-20 20:21:26 +09:00
Hide_D 305eb071a9 전투 종료 코드 구현 2018-08-20 17:24:16 +09:00
Hide_D 10dab69c63 전투 구현 반영 2018-08-20 03:48:54 +09:00
Hide_D 60ed594996 전투 구현 반영 2018-08-20 03:46:59 +09:00
Hide_D e60ddb3ee1 전투 구현 반영 2018-08-20 03:14:56 +09:00
Hide_D 26b0992285 전투 구현 반영 2018-08-19 03:47:28 +09:00
Hide_D 63f3ac807c 전투 구현 반영 2018-08-19 03:45:43 +09:00
Hide_D ed1c33eac0 전투 구현 반영 2018-08-19 03:30:47 +09:00
Hide_D e7b7fd0bcc 치료가 '필살', '회피'와 중복 가능. 전특과 의술 아이템의 치료 효과 증폭 2018-08-19 03:00:08 +09:00
Hide_D 79d2b04721 전투 구현 반영 2018-08-19 02:57:25 +09:00
Hide_D 5a8ab2d29c 전투 구현 반영 2018-08-19 02:33:42 +09:00
Hide_D ed527ac394 전투 코드 반영 2018-08-18 23:18:40 +09:00
Hide_D bf09f48196 전투 구현 반영 2018-08-18 22:21:25 +09:00
Hide_D 2a5af15aef 전투 코드 반영 2018-08-18 21:24:02 +09:00
Hide_D 1f8fe35e25 성벽 전투시 깎이는 성벽이 기존 대비 1/2 2018-08-18 20:46:30 +09:00
Hide_D 5979273a64 코드 중간 반영 2018-08-18 20:45:59 +09:00
Hide_D ef8c9e3968 전투 엔진 중간 반영 2018-08-18 19:04:13 +09:00
Hide_D baa9fdb660 유틸리티 함수 추가 2018-08-18 16:59:34 +09:00
Hide_D 35a860bb38 충차 성벽 보정 버그 수정 2018-08-18 15:18:40 +09:00
Hide_D 286939dc2c CriticalScore2, getCrew 이동 2018-08-18 14:02:53 +09:00
Hide_D dd5b1dbdd8 전투 추가 구현 2018-08-18 10:53:04 +09:00
Hide_D fb8d3a038d 새 전투 엔진 중간 반영 2018-08-18 02:26:27 +09:00
Hide_D ea5a25a671 전투 파일 추가 작성중
전투 코드 추가 준비

추가 구현
2018-08-14 23:11:03 +09:00
Hide_D d21fc4ab1d 새 전투 엔진 준비 2018-08-12 22:23:53 +09:00
Hide_D 3ae3974866 수극 사용 로그 버그 수정 2018-08-12 13:25:24 +09:00
Hide_D 71ffc3087e 전투 공식 핫픽스 2018-08-11 08:49:23 +09:00
Hide_D 8f406489d4 전콘 용량을 30KB로 증가 2018-08-10 19:58:31 +09:00
Hide_D a08d270968 루드라사움 지도 업데이트 2018-08-10 02:22:31 +09:00
Hide_D 48f13e4b82 루드라사움 스탯 수정 2018-08-08 03:47:04 +09:00
Hide_D 51060f0e4b 루드라사움 지도 업데이트 2018-08-08 03:36:00 +09:00
Hide_D c583109046 루드라사움 패치 2018-08-08 03:21:42 +09:00
Hide_D cf05b693f1 엑셀 파일에 빙의 불가 장수 목록 개념 추가 2018-08-08 02:48:17 +09:00
Hide_D d248c1ab0d 빙의가 불가능한 general_neutral 항목 추가 2018-08-08 02:45:41 +09:00
Hide_D 34623fca94 이민족 코드를 5에서 9로 이동. 그에따른 추가 코드 변경 2018-08-08 02:31:49 +09:00
Hide_D 975bdd5897 토너먼트 중복 참가 방지. 자동 참가시 돈을 받지 않음 2018-08-08 01:54:57 +09:00
Hide_D 1b3380c2ca 성벽을 때렸을 때 차숙이 오르지 않는 버그 해결 2018-08-07 04:00:31 +09:00
Hide_D bb707b4a03 명성 / 계급 계산식을 for loop 없앰 2018-08-06 01:23:39 +09:00
Hide_D acb3b6ac85 물자 조달로 올라가는 명성, 계급의 양을 다른 내정과 비슷하게 변경 2018-08-06 00:46:22 +09:00
Hide_D 80f6985f5f 지도 툴팁 line break 없앰 2018-07-30 03:23:01 +09:00
Hide_D 5e3a9c0579 지도 툴팁 너비 수정 2018-07-30 02:13:46 +09:00
Hide_D b30d62d483 루도라사움 지도 위치 수정 2018-07-30 02:11:51 +09:00
Hide_D 0ea1fdbd19 지도 출력 변경 2018-07-30 02:07:02 +09:00
Hide_D f068586f74 지도를 변경 가능하도록 업데이트 2018-07-30 02:00:53 +09:00
Hide_D 463f462e24 j_map_history에서 year가 0인 경우 2018-07-30 01:47:33 +09:00
Hide_D e0c4e3c58e 장수 생성시 기본 타입 2018-07-30 01:42:42 +09:00
Hide_D 5aa3ef38ba 연감용 루드라사움 지도 추가 2018-07-30 01:34:39 +09:00
Hide_D 827277f6a3 버그 수정 2018-07-30 01:26:12 +09:00
Hide_D 46389341db 루드라사움을 위한 시스템 보정 2018-07-30 00:37:39 +09:00
Hide_D a58f05a295 에러메시지를 VSCode에서 바로 이동하기 쉽도록 변경 2018-07-29 23:43:36 +09:00
Hide_D c0b0a0fe92 루드라사움 지도 연결 수정 2018-07-29 23:41:35 +09:00
Hide_D e9f471dd6f Neo 루드라사움 준비 2018-07-29 23:26:19 +09:00
Hide_D 7917c5dddb 부대편성 버그 수정 2018-07-29 16:20:43 +09:00
Hide_D de4541a3d9 부대 편성 일부 수정 2018-07-29 13:57:10 +09:00
Hide_D 77a496baa7 암행부 추가 확장 2018-07-28 02:38:19 +09:00
Hide_D 86e863de09 암행부 너비 추가 수정 2018-07-28 02:33:42 +09:00
Hide_D c2cfd217c2 암행부 턴 표기 수정 2018-07-28 02:02:50 +09:00
Hide_D f2366a61b0 IE11 모병창 UI 버그 수정 2018-07-28 01:58:35 +09:00
Hide_D 9959393dee IE 메인페이지 깨짐 일부 수정 2018-07-28 01:38:53 +09:00
Hide_D 16facf98f1 submit_btn 버그 수정 2018-07-28 01:32:00 +09:00
Hide_D bc8ce8832a 모/징병 페이지 변경 2018-07-28 01:24:23 +09:00
Hide_D 20bcf960ef 로그인 페이지를 모바일에서도 조금 더 잘보이게 변경 2018-07-27 18:56:01 +09:00
Hide_D 5cecd3e995 로그인 페이지가 약관 등에 가리지 않도록 변경 2018-07-27 18:47:48 +09:00
Hide_D d7ead25ea4 1턴에 어쩌다 휴식턴이 입력되는 버그 수정 2018-07-27 18:14:16 +09:00
Hide_D 75c0c375d1 장수 호칭 변경 2018-07-27 03:03:25 +09:00
Hide_D 5db4913292 세력일람 장수 표기순 변경 2018-07-27 02:39:26 +09:00
Hide_D a6a53b1d0d Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2018-07-27 02:34:02 +09:00
Hide_D 81a0c0e120 세력일람 업데이트 2018-07-27 02:33:56 +09:00
Hide_D 0dae71a644 회피 디버그 수정 2018-07-26 17:13:27 +09:00
Hide_D f8eedaa3ea 전투 디버그 2018-07-26 15:40:46 +09:00
Hide_D ce2d97a7e7 전투 회피 코드 디버깅 적용 2018-07-26 15:39:34 +09:00
Hide_D 2cb570eaca foreach reference loop 버그 2018-07-26 00:12:12 +09:00
Hide_D c8c4352957 기존 도시/암행부 스크립트 통합. 2018-07-25 23:58:58 +09:00
Hide_D a311db4555 서버 관리 창에 에러 로그 보기 버튼 추가 2018-07-23 23:44:48 +09:00
Hide_D 05c515b2da j_map_history에서 fallback arg 제거 2018-07-23 23:30:53 +09:00
Hide_D c1acf2b0fe Trace의 모든 내용이 나오도록 수정 2018-07-23 23:26:32 +09:00
Hide_D 803a2407eb 에러 로그 보기 기능 추가 2018-07-23 23:19:39 +09:00
Hide_D a87945d1fb 에러 로그 업데이트 2018-07-23 22:54:06 +09:00
Hide_D 30793e68df 에러 로그용 클래스 설정 2018-07-23 22:50:22 +09:00
Hide_D 9c666bf7a9 FileDB 클래스 추가 2018-07-23 22:37:30 +09:00
Hide_D eff1dd7c34 라이브러리 업데이트 catfan/medoo 추가 2018-07-23 21:27:26 +09:00
Hide_D e79a33ebb0 NPC 군주의 호전성 추가(?) 2018-07-23 02:56:33 +09:00
Hide_D cb0adfdeaf npc attackable 보완 2018-07-23 02:50:58 +09:00
Hide_D 6b135c343c NPC의 선포 대상을 '국력'이 낮은 국가에 더 잘 하도록 변경 2018-07-23 01:49:43 +09:00
Hide_D 6c92db524b 선포 코드를 조금더 직관적으로 수정 2018-07-23 01:28:34 +09:00
Hide_D b8dfd1c041 징,모병시 민심이 떨어지지 않는 버그 수정 2018-07-22 15:39:53 +09:00
Hide_D 54d6347c1d 사령부 휴식 커맨드가 제대로 안보이는 문제 해결 2018-07-22 15:10:37 +09:00
Hide_D 4ea6e90600 연감에 serverID가 잘못된 경우 해결 2018-07-22 03:37:14 +09:00
Hide_D 4c7628a247 부대편성의 '집합' 확인 코드가 하드코딩인 부분 수정 2018-07-22 03:28:10 +09:00
revofpla 6c7334155a 필살확률 무조건 최소 50%인 버그 픽스 2018-07-21 13:49:15 +09:00
revofpla 480e3ea974 체섭 버그로 인한 핫픽스 1차
- 징병 숙련 100배 문제
 - 모병 비용 2배로 계산 안되는 문제
2018-07-21 13:12:52 +09:00
Hide_D 1f639a5bc6 애니집결 시나리오 번호 변경 2018-07-20 19:53:21 +09:00
Hide_D ccf3b07c3a 애니집결 업데이트 2018-07-20 19:51:11 +09:00
Hide_D d8508f2b72 충차가 1등급 되기만 하면 쓸 수 있던 버그 수정 2018-07-20 10:44:14 +09:00
Hide_D 5e13961ec8 protected인 자료에 접근해서 발생하는 문제 수정 2018-07-20 10:05:08 +09:00
Hide_D 80b1139371 버튼 너비 수정 2018-07-20 09:12:37 +09:00
Hide_D 635b41765c 계정 관리 창 살짝 넓힘 2018-07-20 09:08:04 +09:00
Hide_D 4b03686aa2 숙련 단련 버그 수정 2018-07-20 09:01:50 +09:00
Hide_D bfb0d8d639 message 템플릿 버그 수정 2018-07-20 00:06:03 +09:00
Hide_D 93d4a0211d 등용장의 경우에도 누를수 없는 경우 수정 2018-07-19 23:59:27 +09:00
Hide_D cd31bc69ef 추방 버그 수정 2018-07-19 23:13:05 +09:00
Hide_D 4a7b84d6de 외교 서신 레벨 지정 2018-07-19 22:19:26 +09:00
Hide_D 3142714c11 리셋 첫 해에는 추방해도 제약 없음 2018-07-19 21:25:00 +09:00
Hide_D 7ea10416a9 임관 권유 메시지 창 2018-07-19 21:03:42 +09:00
Hide_D 3e427db0f1 relativeYear에 음수 불가 2018-07-19 20:53:46 +09:00
Hide_D 9f7b18d294 시작 시 develcost가 0인 버그 해결 2018-07-19 20:50:29 +09:00
Hide_D 9af0e351b8 Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2018-07-19 20:06:51 +09:00
Hide_D 5c6aa2340d 공백지 시나리오에 특기 연령 문제 해결 2018-07-19 20:06:39 +09:00
Hide_D 4424ec48cf 전투시 병종 명 버그 수정 2018-07-19 10:59:01 +09:00
Hide_D 61be34581e 반복 버튼 키움 2018-07-19 02:33:59 +09:00
Hide_D 731978356d Credit 양식 추가 2018-07-19 02:29:03 +09:00
Hide_D d5223ad1ab 리셋 시 사령부 Command encode가 제대로 이뤄지지 않았던 버그 수정 2018-07-19 01:42:16 +09:00
Hide_D 7cfdfab198 연감에서도 비교적 빠르게 동작하도록 설정 2018-07-19 01:31:13 +09:00
Hide_D eb70e51ac1 실시간 맵은 캐싱하도록 처리 2018-07-19 01:21:00 +09:00
Hide_D 1d48e7c7ae 영웅 난무 220 제목 변경 2018-07-19 00:51:47 +09:00
Hide_D d6fc9fc8c3 지도가 들어간 곳에 부트스트랩 추가 2018-07-19 00:46:15 +09:00
Hide_D 8ada0976fe 연감에 부트스트랩 없는 문제 해결 2018-07-19 00:44:01 +09:00
Hide_D 389ff5e9a4 지도에 도시명 켬끔 추가 2018-07-19 00:39:05 +09:00
Hide_D 5179e0228c 최대 스탯 표기 변경 2018-07-18 23:44:41 +09:00
Hide_D 2268526314 내 정보 페이지 툴팁 안나오는 문제 2018-07-18 23:14:52 +09:00
Hide_D db4bc0eafe 도시 좌표 업데이트 2018-07-18 23:11:02 +09:00
Hide_D 6edaf79df1 출력 병종 에러 2018-07-18 22:26:15 +09:00
Hide_D 79cead3b59 도시 css contain 2018-07-18 22:24:22 +09:00
Hide_D db1b12b85c 훈련에서 사기 하락 문구 삭제 2018-07-18 16:54:25 +09:00
Hide_D 9360b7675a 천인 강림 극 소형맵 2018-07-18 14:23:12 +09:00
Hide_D 9c82fd17fe 훈련시 사기 감소하지 않음 2018-07-18 11:18:33 +09:00
Hide_D 3a4665e473 맵 업데이트 2018-07-18 10:46:33 +09:00
Hide_D b34f4648ee 호로->사수, 몇몇 소성들 다시 진,수로 롤백 2018-07-18 10:41:06 +09:00
Hide_D 0de786d2ea 쿼리 받아오는 것 수정 2018-07-18 09:28:53 +09:00
Hide_D ec7aafa1ff history 받아오는 버그 수정 2018-07-18 09:28:10 +09:00
Hide_D 30c219716d 오타 수정 2018-07-18 09:08:20 +09:00
Hide_D 5dd47cb89b 오타수정 2018-07-18 09:05:36 +09:00
Hide_D abe856bd3f 버그 수정. 오타 수정 2018-07-18 08:24:09 +09:00
Hide_D 6ecb009466 오타 수정 2018-07-18 04:51:19 +09:00
Hide_D 3b4b2383a8 $me 버그 2018-07-18 04:50:17 +09:00
Hide_D 4ddd46c4a2 모병코드 2018-07-18 04:49:30 +09:00
Hide_D 69ec2469b4 쌀 검사 코드 2018-07-18 04:47:28 +09:00
Hide_D 5789af801a 징모병창 코스트 2018-07-18 04:44:12 +09:00
Hide_D 7171b6302b formattext 2018-07-18 04:41:08 +09:00
Hide_D 51d4818b1e gameStor 값 버그 2018-07-18 04:40:18 +09:00
Hide_D 1c2875e7fc 모병창 수정 2018-07-18 04:37:00 +09:00
Hide_D 5048a88310 징병창 우선 부활 2018-07-18 04:30:54 +09:00
Hide_D aef37f4362 징모병창 변수명 에러 2018-07-18 04:18:15 +09:00
Hide_D d04641041b 아이템 return 값 수정 2018-07-18 04:15:28 +09:00
Hide_D 67b2ccea86 급한대로 도시명 띄움 2018-07-18 04:10:07 +09:00
Hide_D 5ff9ca3c99 miniche가 최신 버전이 아닌 버그 수정 2018-07-18 03:44:32 +09:00
Hide_D fe55df8b2f 버그 체크 2018-07-18 03:41:45 +09:00
Hide_D 457f605898 버그 수정 2018-07-18 03:32:47 +09:00
Hide_D 0f2625133f 미니체 basemap 2018-07-18 03:05:36 +09:00
Hide_D fa34dbdf6f 초기 버그 수정 2018-07-18 03:04:59 +09:00
Hide_D 050913b0b4 영난 1c 2018-07-18 02:58:56 +09:00
Hide_D a47e47d42c 도시 정보 업데이트 2018-07-18 02:57:08 +09:00
Hide_D 43d994b59a credit 링크 추가 2018-07-18 02:31:15 +09:00
Hide_D e8204d46ce 커스텀 맵 준비 2018-07-18 00:25:51 +09:00
Hide_D fece659cfb 변수명 통일 2018-07-16 02:56:52 +09:00
Hide_D 695265b299 병종 코드를 GameUnitConst, GameUnitDetail에 기반하도록 변경 2018-07-16 02:54:47 +09:00
Hide_D b652ed0b33 병종 테이블에 상성 값 확장 2018-07-16 01:43:11 +09:00
Hide_D 9a641552e4 전투 코드 반영 중 2018-07-15 01:46:29 +09:00
Hide_D 3d18aeb5bc 징병, 모병 form 수정 2018-07-15 01:01:36 +09:00
Hide_D b545afce50 모병, 징병 코드 재 구현. 능력치 상승/감소 코드 재구현 2018-07-14 22:41:10 +09:00
Hide_D 8fca98c0c9 ActionLogger rollback 추가 2018-07-14 18:23:31 +09:00
Hide_D 0a98c71dfe 현재까지 작업물 보강, 모.징병 페이지 개선 중 2018-07-14 18:17:37 +09:00
Hide_D ed75f39094 ActionLogger 보강 2018-07-14 18:17:18 +09:00
Hide_D 456245f23a ActionLogger 추가 2018-07-14 17:53:08 +09:00
Hide_D b4529c9338 병종값 변경 2018-07-13 00:41:56 +09:00
Hide_D 0ca7a8ab8a 병종 테이블에 '병종 타입' 지정, 턴 커맨드를 json array로 변경 2018-07-13 00:12:12 +09:00
Hide_D 02f2209e8f GameConst에 mapName과 unitSet추가 2018-07-12 01:59:32 +09:00
Hide_D fb72d02912 d_setting 디렉도리 보관 방식 변경 2018-07-12 01:56:46 +09:00
Hide_D 665fb25fc1 기본 파일 추가 2018-07-12 01:02:28 +09:00
Hide_D 742c3c7156 맵 규격 재 정의 2018-07-12 01:00:24 +09:00
Hide_D 637dbbba0d 새 지도 준비를 위해 커밋 2018-07-12 00:20:43 +09:00
Hide_D f2a3bc4626 메시지함 높이 고정을 최소 높이로 변경 2018-07-11 23:49:57 +09:00
Hide_D e8ffa44544 메시지함 사라지는 버그 수정? 2018-07-11 23:04:38 +09:00
Hide_D bc09287666 도움 주신 분 임시 삭제. 나중에 Credit으로 되살리기로 2018-07-11 22:37:36 +09:00
Hide_D 392d9055fe td tr 되돌려놓음 2018-07-11 22:18:08 +09:00
Hide_D 0ee833d7ae list 일부 수정. tfoot 안에 tr td없는거 수정 2018-07-11 22:17:03 +09:00
Hide_D 3074bc00d7 지도 표기에서 box 표기 문제로 일부 수정 2018-07-11 22:04:20 +09:00
Hide_D cb6fb590c4 귀병, 환술 설명 수정 2018-07-11 21:53:13 +09:00
Hide_D a7270b2cd2 장수 성격, 아이템 설명 툴팁 추가 2018-07-11 21:50:01 +09:00
Hide_D 0d925af065 tooltip html trim 추가 2018-07-11 20:52:46 +09:00
Hide_D 7c7991e8ae 특기 없을 때 텍스트 수정 2018-07-11 20:51:13 +09:00
Hide_D 54461b6ea4 특기가 없는 경우에도 tooltip 띄우도록 2018-07-11 17:03:47 +09:00
Hide_D 6a17497fbd 빙의 시에도 전특 표기 2018-07-11 03:27:27 +09:00
Hide_D 84f18aa4b6 특기 전 페이지에 반영 2018-07-11 03:03:52 +09:00
Hide_D 73ab38563f 특기 마우스 오버 1차 적용 2018-07-11 02:47:31 +09:00
Hide_D 1f2b40e4d4 message form box sizing 변경. 메인 페이지에 bootstrap css 적용 2018-07-11 01:31:59 +09:00
Hide_D 1d920c5935 darkly 적용 2018-07-11 01:19:24 +09:00
Hide_D 037a1e9c0c 툴팁 준비 2018-07-11 01:15:22 +09:00
Hide_D 87e324d4d9 bootstrap 최신 버전으로 2018-07-11 01:15:02 +09:00
Hide_D d1e9b489e3 공성 전특 버그 수정. 전특 설명을 위한 텍스트 추가 2018-07-11 00:53:10 +09:00
Hide_D 34f1d538d1 세력도시에서 n장, m장 임명이 불가능한 버그 수정 2018-07-07 05:13:22 +09:00
Hide_D fb8d2a2e01 구버전 첩보 마이그레이션시 지도 표기 버그 수정 2018-07-07 04:58:19 +09:00
Hide_D 837db5183e 첩보를 join '|' 에서 json dict로 변경 2018-07-07 04:39:44 +09:00
177 changed files with 13653 additions and 5586 deletions
+1
View File
@@ -45,3 +45,4 @@ test.php
phpinfo.php
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
*.sqlite3
+2 -1
View File
@@ -19,7 +19,8 @@
"pguardiario/phpuri": "^1.0",
"symfony/lock": "^4.1",
"ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7"
"xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^1.5"
},
"autoload": {
"psr-4": {
Generated
+70 -11
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "43da7d5e9d8441faa4311f32b16ee1c0",
"content-hash": "3fceaf3c2925068c7e757ab12036e29e",
"packages": [
{
"name": "brandonwamboldt/utilphp",
@@ -52,6 +52,65 @@
],
"time": "2015-02-02T17:56:14+00:00"
},
{
"name": "catfan/medoo",
"version": "v1.5.7",
"source": {
"type": "git",
"url": "https://github.com/catfan/Medoo.git",
"reference": "8d90cba0e8ff176028847527d0ea76fe41a06ecf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/catfan/Medoo/zipball/8d90cba0e8ff176028847527d0ea76fe41a06ecf",
"reference": "8d90cba0e8ff176028847527d0ea76fe41a06ecf",
"shasum": ""
},
"require": {
"ext-pdo": "*",
"php": ">=5.4"
},
"suggest": {
"ext-pdo_dblib": "For MSSQL or Sybase database on Linux/UNIX platform",
"ext-pdo_mysql": "For MySQL or MariaDB database",
"ext-pdo_oci": "For Oracle database",
"ext-pdo_oci8": "For Oracle version 8 database",
"ext-pdo_pqsql": "For PostgreSQL database",
"ext-pdo_sqlite": "For SQLite database",
"ext-pdo_sqlsrv": "For MSSQL database"
},
"type": "framework",
"autoload": {
"psr-4": {
"Medoo\\": "/src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Angel Lai",
"email": "angel@catfan.me"
}
],
"description": "The lightest PHP database framework to accelerate development",
"homepage": "https://medoo.in",
"keywords": [
"database",
"lightweight",
"mariadb",
"mssql",
"mysql",
"oracle",
"php framework",
"postgresql",
"sql",
"sqlite"
],
"time": "2018-06-14T18:59:08+00:00"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.10.0",
@@ -318,16 +377,16 @@
},
{
"name": "leafo/scssphp",
"version": "v0.7.6",
"version": "v0.7.7",
"source": {
"type": "git",
"url": "https://github.com/leafo/scssphp.git",
"reference": "585f6ae84de62ffecf69c23805f25d78d7e4b794"
"reference": "1d656f8c02a3a69404bba6b28ec4e06edddf0f49"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/leafo/scssphp/zipball/585f6ae84de62ffecf69c23805f25d78d7e4b794",
"reference": "585f6ae84de62ffecf69c23805f25d78d7e4b794",
"url": "https://api.github.com/repos/leafo/scssphp/zipball/1d656f8c02a3a69404bba6b28ec4e06edddf0f49",
"reference": "1d656f8c02a3a69404bba6b28ec4e06edddf0f49",
"shasum": ""
},
"require": {
@@ -366,7 +425,7 @@
"scss",
"stylesheet"
],
"time": "2018-05-24T02:18:53+00:00"
"time": "2018-07-22T01:22:08+00:00"
},
{
"name": "league/plates",
@@ -751,16 +810,16 @@
},
{
"name": "symfony/lock",
"version": "v4.1.0",
"version": "v4.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/lock.git",
"reference": "a1df50492e927ad00ca271f29adb2949a14f2a5a"
"reference": "d508b5dd92272cb74300396ecaadde969d0f7976"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/lock/zipball/a1df50492e927ad00ca271f29adb2949a14f2a5a",
"reference": "a1df50492e927ad00ca271f29adb2949a14f2a5a",
"url": "https://api.github.com/repos/symfony/lock/zipball/d508b5dd92272cb74300396ecaadde969d0f7976",
"reference": "d508b5dd92272cb74300396ecaadde969d0f7976",
"shasum": ""
},
"require": {
@@ -808,7 +867,7 @@
"redlock",
"semaphore"
],
"time": "2018-05-30T07:26:09+00:00"
"time": "2018-06-21T11:15:46+00:00"
},
{
"name": "vlucas/valitron",
+1
View File
@@ -61,6 +61,7 @@ a.just_link {
}
button.with_skin {
padding:0 4px;
background-color: black; color: white;
font-family: '맑은 고딕';
font-size: 13px;
+11
View File
@@ -87,6 +87,17 @@ input::-webkit-input-placeholder {
align-items: center;
}
.full-content {
position:fixed;
left:0;
top:0;
width:100%;
height:100%;
margin:0;
padding:0;
z-index:800;
}
#btn_kakao_login{
cursor: pointer;
height:46px;
+1 -1
View File
@@ -1,7 +1,7 @@
@charset "utf-8";
#user_info_container{
width:500px;
width:550px;
position:absolute;
left:50%;
margin-left:-250px;
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-4
View File
File diff suppressed because one or more lines are too long
+67 -21
View File
@@ -49,40 +49,86 @@ function getFriendlyErrorType($type)
return "{$type}";
}
function getExceptionTraceAsString($exception) {
//https://gist.github.com/abtris/1437966
$rtn = "";
$count = 0;
$rtn = [];
foreach ($exception->getTrace() as $frame) {
$args = "";
if (isset($frame['args'])) {
$args = array();
foreach ($frame['args'] as $arg) {
if (is_string($arg)) {
$args[] = "'" . $arg . "'";
} elseif (is_array($arg)) {
$args[] = "Array";
} elseif (is_null($arg)) {
$args[] = 'NULL';
} elseif (is_bool($arg)) {
$args[] = ($arg) ? "true" : "false";
} elseif (is_object($arg)) {
$args[] = get_class($arg);
} elseif (is_resource($arg)) {
$args[] = get_resource_type($arg);
} else {
$args[] = $arg;
}
}
$args = join(", ", $args);
}
$rtn[] = sprintf( "#%s %s:%s %s(%s)",
$count,
isset($frame['file']) ? $frame['file'] : 'unknown file',
isset($frame['line']) ? $frame['line'] : 'unknown line',
(isset($frame['class'])) ? $frame['class'].$frame['type'].$frame['function'] : $frame['function'],
$args );
$count++;
}
return $rtn;
}
function logError(string $err, string $errstr, array $trace){
$fdb = FileDB::db(ROOT.'/d_log/err_log.sqlite3', ROOT.'/f_install/sql/err_log.sql');
$date = date("Ymd_His");
$trace = array_map(function(string $text){
return str_replace(ROOT, '{ROOT}', $text);
}, $trace);
$fdb->insert('err_log', [
'date'=>$date,
'err'=>$err,
'errstr'=>$errstr,
'trace'=>Json::encode($trace)
]);
}
function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, int $errline, array $errcontext){
if (!(error_reporting() & $errno)) {
// This error code is not included in error_reporting, so let it fall
// through to the standard PHP error handler
return false;
}
$date = date("Ymd_His");
$e = new \Exception();
$data = Json::encode([
'date'=>$date,
'err'=>getFriendlyErrorType($errno),
'errstr'=>$errstr,
'trace'=>explode("\n", $e->getTraceAsString())
], Json::PRETTY);
file_put_contents(ROOT.'/d_log/err_log.txt',"$data\n", FILE_APPEND);
logError(
getFriendlyErrorType($errno),
$errstr,
getExceptionTraceAsString($e)
);
}
set_error_handler("\sammo\logErrorByCustomHandler");
function logExceptionByCustomHandler(\Throwable $e){
$date = date("Ymd_His");
$data = Json::encode([
'date'=>$date,
'err'=>get_class($e),
'errstr'=>$e->getMessage(),
'trace'=>explode("\n", $e->getTraceAsString())
], Json::PRETTY);
file_put_contents(ROOT.'/d_log/err_log.txt',"$data\n", FILE_APPEND);
logError(
get_class($e),
$e->getMessage(),
getExceptionTraceAsString($e)
);
echo $e->getTraceAsString();
throw $e;
}
+1
View File
@@ -15,6 +15,7 @@ require(__dir__.'/../vendor/autoload.php');
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery.validate.min.js')?>
<?=WebUtil::printJS('../e_lib/sha512.min.js')?>
<?=WebUtil::printJS('../js/common.js')?>
<?=WebUtil::printJS('../js/install.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../css/install.css')?>
+10
View File
@@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS `err_log` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`date` TEXT NOT NULL,
`err` TEXT NOT NULL,
`errstr` TEXT NOT NULL,
`trace` TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS `date` ON `err_log` (
`date` DESC
);
+76 -8
View File
@@ -41,18 +41,86 @@
url('_tK_gameImagePath_/winter.gif') no-repeat right;
}
.map_spring .map_body{
background: url('_tK_gameImagePath_/map1.jpg') no-repeat;
/*체 지도*/
.map_theme_che.map_spring .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_spring.jpg') no-repeat;
}
.map_summer .map_body{
background: url('_tK_gameImagePath_/map2.jpg') no-repeat;
.map_theme_che.map_summer .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_summer.jpg') no-repeat;
}
.map_fall .map_body{
background: url('_tK_gameImagePath_/map3.jpg') no-repeat;
.map_theme_che.map_fall .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_fall.jpg') no-repeat;
}
.map_winter .map_body{
background: url('_tK_gameImagePath_/map4.jpg') no-repeat;
.map_theme_che.map_winter .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_winter.jpg') no-repeat;
}
.map_theme_che .map_bgroad{
background: url('_tK_gameImagePath_/map/che/che_road.png') no-repeat;
}
/*미니체 지도*/
.map_theme_miniche.map_spring .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_spring.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche.map_summer .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_summer.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche.map_fall .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_fall.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche.map_winter .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_winter.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche .map_bgroad{
background: url('_tK_gameImagePath_/map/che/miniche_road.png') no-repeat;
background-size: 700px 500px;
}
/*루드라사움 지도*/
.map_theme_ludo_rathowm .map_bglayer1{
background: url('_tK_gameImagePath_/map/ludo_rathowm/back.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_ludo_rathowm .map_bgroad{
background: url('_tK_gameImagePath_/map/ludo_rathowm/road.png') no-repeat;
background-size: 700px 500px;
}
.map_theme_ludo_rathowm.map_detail.map_spring .map_title_text{
background:
url('_tK_gameImagePath_/spring.gif') no-repeat right;
}
.map_theme_ludo_rathowm.map_detail.map_summer .map_title_text{
background:
url('_tK_gameImagePath_/summer.gif') no-repeat right;
}
.map_theme_ludo_rathowm.map_detail.map_fall .map_title_text{
background:
url('_tK_gameImagePath_/fall.gif') no-repeat right;
}
.map_theme_ludo_rathowm.map_detail.map_winter .map_title_text{
background:
url('_tK_gameImagePath_/winter.gif') no-repeat right;
}
.world_map.map_theme_ludo_rathowm .map_title .map_title_text::before {
color:white;
content:'LP';
margin-right:1ch;
}
+1 -1
View File
@@ -30,7 +30,7 @@ $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
list($turntime, $tnmt_time) = $gameStor->getValuesAsArray(['turntime','tnmt_time']);
[$turntime, $tnmt_time] = $gameStor->getValuesAsArray(['turntime','tnmt_time']);
$query = "select plock from plock";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
+2 -2
View File
@@ -58,7 +58,7 @@ $db = DB::db();
<?php
echo "
<select name=genlist[] size=20 multiple style=color:white;background-color:black;font-size:13>";
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:13px'>";
$generalList = $db->query('SELECT `no`, `name`, npc, `block` FROM general ORDER BY npc, binary(`name`)');
foreach($generalList as $general){
@@ -76,7 +76,7 @@ echo "
</td>
<td width=100 align=center>아이템 지급</td>
<td width=504>
<select name=weap size=1 style=color:white;background-color:black;font-size:13>";
<select name=weap size=1 style='color:white;background-color:black;font-size:13px'>";
for($i=0; $i < 27; $i++) {
echo "
<option value={$i}>{$i}</option>";
+7 -5
View File
@@ -6,6 +6,8 @@ include "func.php";
$btn = Util::getReq('btn');
$weap = Util::getReq('weap', 'int');
$genlist = Util::getReq('genlist', 'array_int');
$msg = Util::getReq('msg', 'string');
extractMissingPostToGlobals();
@@ -93,13 +95,13 @@ switch($btn) {
case "강제 사망":
$date = date('Y-m-d H:i:s');
$db->update('general', [
'turn0'=>0,
'turn0'=>EncodeCommand(0, 0, 0, 0),
'killturn'=>0,
'turntime'=>$date,
], '`no` IN %li', $genlist);
break;
case "특기 부여":
list($year, $month) = $gameStor->getValuesAsArray(['year', 'month']);
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$text = "특기 부여!";
foreach($db->query("SELECT `no`,leader,power,intel,dex0,dex10,dex20,dex30,dex40 FROM general WHERE `no` IN %li", $genlist) as $general){
@@ -314,13 +316,13 @@ switch($btn) {
break;
case "하야입력":
$db->update('general', [
'turn0'=>'00000000000045'
'turn0'=>EncodeCommand(0, 0, 0, 45)
], '`no` IN %li', $genlist);
break;
case "방랑해산":
$db->update('general', [
'turn0'=>'00000000000047',
'turn1'=>'00000000000056'
'turn0'=>EncodeCommand(0, 0, 0, 47),
'turn1'=>EncodeCommand(0, 0, 0, 56)
], '`no` IN %li', $genlist);
break;
case "NPC설정":
+1 -1
View File
@@ -55,7 +55,7 @@ $conlimit = $gameStor->conlimit;
<?php
echo "
<select name=genlist[] size=20 multiple style=color:white;background-color:black;font-size:13>";
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:13px'>";
foreach($db->query('SELECT no,name,npc,block,con from general where ip!=\'\' order by npc,ip') as $general){
$style = "style=;";
+1 -1
View File
@@ -52,7 +52,7 @@ switch($btn) {
break;
case "강제 사망":
$date = date('Y-m-d H:i:s');
DB::db()->query('update general set turn0=0,killturn=0,turntime=%s where no IN %li',$date, $genlist);
DB::db()->query('update general set turn0=%s,killturn=0,turntime=%s where no IN %li',EncodeCommand(0, 0, 0, 0),$date, $genlist);
break;
case "메세지 전달":
//TODO:새 갠메 시스템으로 변경
+6 -1
View File
@@ -26,9 +26,14 @@ increaseRefresh("명장일람", 1);
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1136" />
<title><?=UniqueConst::$serverName?>: 명장일람</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/hallOfFame.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
</head>
<body>
@@ -213,7 +218,7 @@ $itemTypes = [
["명 마", 'horse', function($v){return getHorseName($v);}, 7, 26, []],
["명 검", 'weap', function($v){return getWeapName($v);}, 7, 26, []],
["명 서", 'book', function($v){return getBookName($v);}, 7, 26, []],
["도 구", 'item', function($v){return getItemName($v);}, 7, 26, []],
["도 구", 'item', function($v){return displayItemInfo($v);}, 7, 26, []],
];
$simpleItemTypes = array_map(function($itemType){return $itemType[1];}, $itemTypes);
+32 -22
View File
@@ -41,10 +41,13 @@ if ($type <= 0 || $type > 15) {
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 장수일람</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
</head>
@@ -82,22 +85,22 @@ foreach (getAllNationStaticInfo() as $nation) {
}
switch ($type) { //FIXME: $query 처리 조심.
case 1: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by nation"; break;
case 2: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by leader desc"; break;
case 3: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by power desc"; break;
case 4: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by intel desc"; break;
case 5: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by experience desc"; break;
case 6: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by dedication desc"; break;
case 7: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by level desc"; break;
case 8: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by killturn"; break;
case 1: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by nation"; break;
case 2: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by leader desc"; break;
case 3: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by power desc"; break;
case 4: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by intel desc"; break;
case 5: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by experience desc"; break;
case 6: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by dedication desc"; break;
case 7: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by level desc"; break;
case 8: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by killturn"; break;
default:
case 9: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by connect desc"; break;
case 10: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by experience desc"; break;
case 11: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by personal"; break;
case 12: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by special desc"; break;
case 13: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by special2 desc"; break;
case 14: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by age desc"; break;
case 15: $query = "select picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by npc desc"; break;
case 9: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by connect desc"; break;
case 10: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by experience desc"; break;
case 11: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by personal"; break;
case 12: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by special desc"; break;
case 13: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by special2 desc"; break;
case 14: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by age desc"; break;
case 15: $query = "select no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leader,power,intel,experience,dedication,level,killturn,connect from general order by npc desc"; break;
}
$genresult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect), "");
$gencount = MYDB_num_rows($genresult);
@@ -133,20 +136,20 @@ for ($j=0; $j < $gencount; $j++) {
$lbonus = 0;
}
if ($lbonus > 0) {
$lbonus = "<font color=cyan>+{$lbonus}</font>";
$lbonusText = "<font color=cyan>+{$lbonus}</font>";
} else {
$lbonus = "";
$lbonusText = "";
}
if ($general['injury'] > 0) {
$leader = intdiv($general['leader'] * (100 - $general['injury']), 100);
$power = intdiv($general['power'] * (100 - $general['injury']), 100);
$intel = intdiv($general['intel'] * (100 - $general['injury']), 100);
$leader = "<font color=red>{$leader}</font>{$lbonus}";
$leader = "<font color=red>{$leader}</font>{$lbonusText}";
$power = "<font color=red>{$power}</font>";
$intel = "<font color=red>{$intel}</font>";
} else {
$leader = "{$general['leader']}{$lbonus}";
$leader = "{$general['leader']}{$lbonusText}";
$power = "{$general['power']}";
$intel = "{$general['intel']}";
}
@@ -163,12 +166,19 @@ for ($j=0; $j < $gencount; $j++) {
$imageTemp = GetImageURL($general['imgsvr']);
echo "
<tr>
<tr data-general-id='{$general['no']}'
data-general-wounded='{$general['injury']}'
data-general-leadership='{$general['leader']}'
data-general-leadership-bonus='{$lbonus}'
data-general-power='{$general['power']}'
data-general-intel='{$general['intel']}'
data-is-npc='".($general['npc']>=2?'true':'false')."'
>
<td align=center><img width='64' height='64' src={$imageTemp}/{$general['picture']}></img></td>
<td align=center>$name</td>
<td align=center>{$general['age']}세</td>
<td align=center>".getGenChar($general['personal'])."</td>
<td align=center>".getGenSpecial($general['special'])." / ".getGenSpecial($general['special2'])."</td>
<td align=center>".displayCharInfo($general['personal'])."</td>
<td align=center>".displaySpecialInfo($general['special'])." / ".displaySpecialInfo($general['special2'])."</td>
<td align=center>Lv ".getExpLevel($general['experience'])."</td>
<td align=center>{$nation}</td>
<td align=center>".getHonor($general['experience'])."</td>
+4
View File
@@ -36,11 +36,15 @@ else{
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1136" />
<title><?=UniqueConst::$serverName?>: 명예의 전당</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/hallOfFame.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery.redirect.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJs('js/hallOfFame.js')?>
</head>
+24 -8
View File
@@ -15,7 +15,6 @@ $userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
if(!$serverID){
$serverID = UniqueConst::$serverID;
@@ -25,11 +24,9 @@ if($serverID === UniqueConst::$serverID){
increaseRefresh("연감", 1);
}
$admin = $gameStor->getValues(['startyear','year','month']);
$admin = $gameStor->getValues(['startyear','year','month','map_theme']);
$query = "select con,turntime from general where owner='{$userID}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect), "");
$me = MYDB_fetch_array($result);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner = %i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
@@ -42,9 +39,21 @@ if ($con >= 2) {
[$s_year, $s_month] = $db->queryFirstList('SELECT year, month FROM history WHERE server_id = %s ORDER BY year ASC, month ASC LIMIT 1', $serverID);
$s = $s_year * 12 + $s_month;
if($s_year === null){
echo '인자 에러';
exit();
}
[$e_year, $e_month] = $db->queryFirstList('SELECT year, month FROM history WHERE server_id = %s ORDER BY year DESC, month DESC LIMIT 1', $serverID);
$e = $e_year * 12 + $e_month;
if($serverID !== UniqueConst::$serverID){
$mapTheme = $db->queryFirstField('SELECT map FROM ng_games WHERE server_id=%s', $serverID)?:'che';
}
else{
$mapTheme = $admin['map_theme']??'che';
}
//FIXME: $yearmonth가 올바르지 않을 경우에 처리가 필요.
if($serverID !== UniqueConst::$serverID && !$yearmonth){
$year = $s_year;
@@ -89,11 +98,13 @@ if ($month <= 0) {
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 연감</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/base_map.js')?>
<?=WebUtil::printJS("js/map/theme_{$mapTheme}.js")?>
<?=WebUtil::printJS('js/map.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/map.css')?>
@@ -133,7 +144,7 @@ $history = $db->queryFirstRow('SELECT log,genlog,nation,power,gen,city FROM hist
<tr><td colspan=5 align=center id=bg1>중 원 지 도</td></tr>
<tr height=520>
<td width=698>
<?=getMapHtml();?>
<?=getMapHtml($mapTheme);?>
<td width=139 valign=top><div style='background-color:#cccccc;color:black;text-align:center'>국명</div><?=$history['nation']?></td>
<td width=70 valign=top style='text-align:center'><div style='background-color:#cccccc;color:black;'>국력</div><?=$history['power']?></td>
@@ -158,10 +169,15 @@ $history = $db->queryFirstRow('SELECT log,genlog,nation,power,gen,city FROM hist
<tr><td><?=banner()?> </td></tr>
</table>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
reloadWorldMap({
targetJson:'j_map_history.php?year=<?=$year?>&month=<?=$month?>&serverID=<?=$serverID?>',
showMe:false,
neutralView:true
neutralView:true,
useCachedMap:false,
year:<?=$year?>,
month:<?=$month?>,
});
</script>
</body>
+7 -2
View File
@@ -29,9 +29,14 @@ $sel[$type] = "selected";
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 빙의일람</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
</head>
<body>
@@ -106,8 +111,8 @@ for ($j=0; $j < $gencount; $j++) {
<td align=center>{$general['name2']}</td>
<td align=center>Lv {$general['explevel']}</td>
<td align=center>{$nation}</td>
<td align=center>".getGenChar($general['personal'])."</td>
<td align=center>".getGenSpecial($general['special'])." / ".getGenSpecial($general['special2'])."</td>
<td align=center>".displayCharInfo($general['personal'])."</td>
<td align=center>".displaySpecialInfo($general['special'])." / ".displaySpecialInfo($general['special2'])."</td>
<td align=center>{$general['sum']}</td>
<td align=center>{$general['leader']}</td>
<td align=center>{$general['power']}</td>
+10 -3
View File
@@ -14,6 +14,8 @@ $connect=$db->get();
increaseRefresh("세력도", 2);
checkTurn();
$mapTheme = $gameStor->map_theme??'che';
$query = "select con,turntime from general where owner='{$userID}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$me = MYDB_fetch_array($result);
@@ -29,20 +31,25 @@ if($con >= 2) { printLimitMsg($me['turntime']); exit(); }
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 세력도</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/base_map.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('js/map.js')?>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
$(function(){
reloadWorldMap({
neutralView:true,
showMe:true
showMe:true,
useCachedMap:true
});
});
</script>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/normalize.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -60,7 +67,7 @@ $(function(){
<?=getGeneralPublicRecordRecent(34)?>
</td>
<td width=698>
<?=getMapHtml()?>
<?=getMapHtml($mapTheme)?>
</td>
</tr>
<tr>
+184 -98
View File
@@ -21,9 +21,7 @@ $query = "select no,nation,level,city from general where owner='{$userID}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$me = MYDB_fetch_array($result);
$query = "select nation,level,spy from nation where nation='{$me['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$myNation = MYDB_fetch_array($result);
$myNation = $db->queryFirstRow('SELECT nation,level,spy FROM nation WHERE nation=%i', $me['nation']);
$templates = new \League\Plates\Engine('templates');
@@ -121,27 +119,34 @@ if($me['level'] == 0) {
if($myNation['level'] > 0) {
// 첩보도시도 목록에 추가
$where = 'city=0';
$cities = array_map('intval',explode("|", $myNation['spy']));
foreach($cities as $citySpy) {
$city = intdiv($citySpy, 10);
$where .= " or city='{$city}'";
$rawSpy = $myNation['spy'];
if($rawSpy == ''){
$spyCities = [];
}
else if(strpos($rawSpy, '|') !== false || is_numeric($rawSpy)){
//TODO: 0.8 버전 이후에는 삭제할 것. 이후 버전은 json으로 변경됨.
$spyCities = array_map(function($val){
$val = intval($val);
return intdiv($val, 10);
}, 'intval',explode('|', $myNation['spy']));
}
else{
$spyCities = array_keys(Json::decode($rawSpy));
}
$query = "select city,name,nation from city where {$where}";
$cityresult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$citycount = MYDB_num_rows($cityresult);
for($i=0; $i < $citycount; $i++) {
$city = MYDB_fetch_array($cityresult);
echo "
<option value={$city['city']}";
if($city['city'] == $citylist) { echo " selected"; $valid = 1; }
echo ">==================================================【".StringUtil::padString($city['name'], 4, '_')."】";
if($city['nation'] == 0) echo "공백지";
elseif($me['nation'] == $city['nation']) echo "국==";
else echo "타국==";
echo "============================================</option>";
if($spyCities){
foreach ($db->query('SELECT city,name,nation FROM city WHERE city in %li', $spyCities) as $city) {
echo "<option value={$city['city']}";
if($city['city'] == $citylist) { echo " selected"; $valid = 1; }
echo ">==================================================【".StringUtil::padString($city['name'], 4, '_')."】";
if($city['nation'] == 0) echo "공백지";
elseif($me['nation'] == $city['nation']) echo "본국==";
else echo "국==";
echo "============================================</option>";
}
}
}
@@ -165,7 +170,7 @@ if($valid == 0 && $session->userGrade < 5) {
$city = $db->queryFirstRow('SELECT * FROM city WHERE city=%i', $citylist);
$nation = getNationStaticInfo($city['nation']);
$cityNation = getNationStaticInfo($city['nation']);
//태수, 군사, 시중
$gen1 = $db->queryFirstRow('SELECT `name`, npc FROM general WHERE `no`=%i', $city['gen1']);
@@ -175,81 +180,7 @@ $gen3 = $db->queryFirstRow('SELECT `name`, npc FROM general WHERE `no`=%i', $cit
if($city['trade'] == 0) {
$city['trade'] = "- ";
}
?>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
</table>
<table align=center width=1000 class='tb_layout bg2'>
<tr>
<td colspan=12 align=center style=color:"<?=newColor($nation['color'])?>"; bgcolor=<?=$nation['color']?>>【 <?=CityConst::$regionMap[$city['region']]?> | <?=CityConst::$levelMap[$city['level']]?> 】 <?=$city['name']?></td>
</tr>
<tr>
<td align=center width=46 class=bg1>주민</td>
<td align=center width=140><?=$city['pop']?>/<?=$city['pop2']?></td>
<td align=center width=46 class=bg1>농업</td>
<td align=center width=140><?=$city['agri']?>/<?=$city['agri2']?></td>
<td align=center width=46 class=bg1>상업</td>
<td align=center width=140><?=$city['comm']?>/<?=$city['comm2']?></td>
<td align=center width=46 class=bg1>치안</td>
<td align=center width=140><?=$city['secu']?>/<?=$city['secu2']?></td>
<td align=center width=46 class=bg1>수비</td>
<td align=center width=140><?=$city['def']?>/<?=$city['def2']?></td>
<td align=center width=46 class=bg1>성벽</td>
<td align=center width=140><?=$city['wall']?>/<?=$city['wall2']?></td>
</tr>
<tr>
<td align=center class=bg1>민심</td>
<td align=center><?=$city['rate']?></td>
<td align=center class=bg1>시세</td>
<td align=center><?=$city['trade']?>%</td>
<td align=center class=bg1>인구</td>
<td align=center><?=round($city['pop']/$city['pop2']*100, 2)?>%</td>
<td align=center class=bg1>태수</td>
<td align=center><?=$gen1['name']??'-'?></td>
<td align=center class=bg1>군사</td>
<td align=center><?=$gen2['name']??'-'?></td>
<td align=center class=bg1>시중</td>
<td align=center><?=$gen3['name']??'-'?></td>
</tr>
<tr>
<td align=center class=bg1>장수</td>
<td colspan=11>
<?php
$query = "select name, npc from general where city='{$city['city']}' and nation='{$city['nation']}'"; // 장수 목록
$genresult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$gencount = MYDB_num_rows($genresult);
if($gencount == 0) echo "-";
for($i=0; $i < $gencount; $i++) {
$general = MYDB_fetch_array($genresult);
echo "{$general['name']}, ";
}
?>
</td>
</tr>
</table>
<br>
<table align=center class='tb_layout bg0'>
<thead>
<tr>
<td width=64 align=center class=bg1>얼 굴</td>
<td width=128 align=center class=bg1>이 름</td>
<td width=48 align=center class=bg1>통솔</td>
<td width=48 align=center class=bg1>무력</td>
<td width=48 align=center class=bg1>지력</td>
<td width=78 align=center class=bg1>관 직</td>
<td width=28 align=center class=bg1>守</td>
<td width=78 align=center class=bg1>병 종</td>
<td width=78 align=center class=bg1>병 사</td>
<td width=48 align=center class=bg1>훈련</td>
<td width=48 align=center class=bg1>사기</td>
<td width=280 align=center class=bg1>명 령</td>
</tr></thead><tbody class='bg0' id='general_list'>
<?php
$query = "select npc,mode,no,picture,imgsvr,name,injury,leader,power,intel,level,nation,crewtype,crew,train,atmos,term,turn0,turn1,turn2,turn3,turn4,turn5 from general where city='{$city['city']}' order by dedication desc"; // 장수 목록
$genresult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$gencount = MYDB_num_rows($genresult);
@@ -261,6 +192,9 @@ foreach(getAllNationStaticInfo() as $nation){
$nationlevel[$nation['nation']] = $nation['level'];
}
//도시명 오 적군 0/0(0) 병장(총) 0/0(4) 90병장 0/0 60병장 0/0 수비○ 0/0
$generalsFormat = [];
for($j=0; $j < $gencount; $j++) {
$general = MYDB_fetch_array($genresult);
@@ -335,7 +269,7 @@ for($j=0; $j < $gencount; $j++) {
$turnText = '';
}
echo $templates->render('cityGeneral', [
$generalsFormat[] = [
'ourGeneral'=>$ourGeneral,
'isNPC'=>$isNPC,
'wounded'=>$wounded,
@@ -361,7 +295,159 @@ for($j=0; $j < $gencount; $j++) {
'nation'=>$nation,
'nationName'=>$nationName,
'turnText'=>$turnText
]);
];
}
$generalsName = array_map(function($gen){return $gen['name'];}, $generalsFormat);
$enemyCrew = 0;
$enemyCnt = 0;
$enemyArmedCnt = 0;
$crew90 = 0;
$gen90 = 0;
$crew80 = 0;
$gen80 = 0;
$crew60 = 0;
$gen60 = 0;
$crewDef = 0;
$genDef = 0 ;
$crewTotal = 0;
$armedGenTotal = 0;
$genTotal = 0;
foreach($generalsFormat as $general){
if($general['nation'] == 0){
continue;
}
if($general['nation'] != $myNation['nation']){
$enemyCnt += 1;
$enemyCrew += $general['crew'];
if($general['crew'] > 0){
$enemyArmedCnt += 1;
}
continue;
}
$crewTotal += $general['crew'];
$genTotal += 1;
if($general['crew'] == 0){
continue;
}
$armedGenTotal += 1;
if($general['train'] >= 90 && $general['atmos'] >= 90){
$crew90 += $general['crew'];
$gen90 += 1;
}
$chkDef = false;
if($general['train'] >= 80 && $general['atmos'] >= 80){
$crew80 += $general['crew'];
$gen80 += 1;
if($general['defenceMode'] == 2){
$crewDef += $general['crew'];
$genDef += 1;
$chkDef = true;
}
}
if($general['train'] >= 60 && $general['atmos'] >= 60){
$crew60 += $general['crew'];
$gen60 += 1;
if($general['defenceMode'] == 1 && !$chkDef){
$crewDef += $general['crew'];
$genDef += 1;
$chkDef = true;
}
}
}
?>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
</table>
<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>
</tr>
<tr>
<td align=center width=48 class=bg1>주민</td>
<td align=center width=112><?=$city['pop']?>/<?=$city['pop2']?></td>
<td align=center width=48 class=bg1>농업</td>
<td align=center width=108><?=$city['agri']?>/<?=$city['agri2']?></td>
<td align=center width=48 class=bg1>상업</td>
<td align=center width=108><?=$city['comm']?>/<?=$city['comm2']?></td>
<td align=center width=48 class=bg1>치안</td>
<td align=center width=108><?=$city['secu']?>/<?=$city['secu2']?></td>
<td align=center width=48 class=bg1>수비</td>
<td align=center width=108><?=$city['def']?>/<?=$city['def2']?></td>
<td align=center width=48 class=bg1>성벽</td>
<td align=center width=108><?=$city['wall']?>/<?=$city['wall2']?></td>
</tr>
<tr>
<td align=center class=bg1>민심</td>
<td align=center><?=$city['rate']?></td>
<td align=center class=bg1>시세</td>
<td align=center><?=$city['trade']?>%</td>
<td align=center class=bg1>인구</td>
<td align=center><?=round($city['pop']/$city['pop2']*100, 2)?>%</td>
<td align=center class=bg1>태수</td>
<td align=center><?=$gen1['name']??'-'?></td>
<td align=center class=bg1>군사</td>
<td align=center><?=$gen2['name']??'-'?></td>
<td align=center class=bg1>시중</td>
<td align=center><?=$gen3['name']??'-'?></td>
</tr>
<tr>
<td align=center class=bg1>도시명</td>
<td align=center><?=$city['name']?></td>
<td align=center class=bg1>적군</td>
<td align=center><?=number_format($enemyCrew)?>/<?=number_format($enemyArmedCnt)?>(<?=number_format($enemyCnt)?>)</td>
<td align=center class=bg1>병장(총)</td>
<td align=center><?=number_format($crewTotal)?>/<?=number_format($armedGenTotal)?>(<?=number_format($genTotal)?>)</td>
<td align=center class=bg1>90병장</td>
<td align=center><?=number_format($crew90)?>/<?=number_format($gen90)?></td>
<td align=center class=bg1>60병장</td>
<td align=center><?=number_format($crew60)?>/<?=number_format($gen60)?></td>
<td align=center class=bg1>수비○</td>
<td align=center><?=number_format($crewDef)?>/<?=number_format($genDef)?></td>
</tr>
<tr>
<td align=center class=bg1>장수</td>
<td colspan=11><?=join(', ', $generalsName)?></td>
</tr>
</table>
<br>
<table align=center class='tb_layout bg0'>
<thead>
<tr>
<td width=64 align=center class=bg1>얼 굴</td>
<td width=128 align=center class=bg1>이 름</td>
<td width=48 align=center class=bg1>통솔</td>
<td width=48 align=center class=bg1>무력</td>
<td width=48 align=center class=bg1>지력</td>
<td width=78 align=center class=bg1>관 직</td>
<td width=28 align=center class=bg1>守</td>
<td width=78 align=center class=bg1>병 종</td>
<td width=78 align=center class=bg1>병 사</td>
<td width=48 align=center class=bg1>훈련</td>
<td width=48 align=center class=bg1>사기</td>
<td width=280 align=center class=bg1>명 령</td>
</tr></thead>
<tbody class='bg0' id='general_list'>
<?php
foreach($generalsFormat as $general){
echo $templates->render('cityGeneral', $general);
}
?>
</tbody>
+5 -1
View File
@@ -48,6 +48,10 @@ if ($me['level'] >= 5) {
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 내무부</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -221,7 +225,7 @@ if ($budgetricediff > 0) {
<tr><td colspan=2 align=center bgcolor=orange>국 가 방 침 &amp; 임관 권유 메시지</td></tr>
<tr><td colspan=2 class=bg1>국가 방침 <textarea <?=$read?> maxlength=16000 rows="5" style="color:white;background-color:black;width:830px;" name=msg><?=$nation['msg']?></textarea><input type=<?=$btn?> name=btn value=국가방침></td></tr>
<tr><td colspan=2 class=bg1>임관 권유 <input type=text <?=$read?> maxlength=1000 style=color:white;background-color:black;width:830px; name=scoutmsg value='<?=$nation['scoutmsg']?>'><input type=<?=$btn?> name=btn value=임관권유></td></tr>
<tr><td colspan=2>870 x 200px 넘는 크기를 점유할 시 통보없이 제한될 수 있습니다.</td></tr>
<tr><td colspan=2>870px x 200px어서는 내용은 표시되지 않습니다.</td></tr>
<tr><td colspan=2 height=10></td></tr>
<tr><td colspan=2 align=center bgcolor=green>예 산 &amp; 정 책</td></tr>
<tr>
+12 -6
View File
@@ -13,6 +13,8 @@ $connect=$db->get();
increaseRefresh("중원정보", 1);
$mapTheme = $gameStor->map_theme??'che';
$query = "select no,nation from general where owner='{$userID}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$me = MYDB_fetch_array($result);
@@ -45,11 +47,11 @@ for($i=0; $i < $nationcount; $i++) {
}
$realConflict = [];
foreach ($db->queryAllLists('SELECT city, `name`, conflict FROM city WHERE conflict!=%s', '{}') as list(
foreach ($db->queryAllLists('SELECT city, `name`, conflict FROM city WHERE conflict!=%s', '{}') as [
$cityID,
$cityName,
$rawConflict
))
])
{
$conflict = Json::decode($rawConflict);
if (count($conflict)<2) {
@@ -78,21 +80,25 @@ foreach ($db->queryAllLists('SELECT city, `name`, conflict FROM city WHERE confl
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 중원 정보</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/base_map.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('js/map.js')?>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
$(function(){
reloadWorldMap({
neutralView:true,
showMe:true
showMe:true,
useCachedMap:true
});
});
</script>
<?=WebUtil::printCSS('css/normalize.css')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/map.css')?>
@@ -214,7 +220,7 @@ for($i=0; $i < $nationcount; $i++) {
</tr>
<tr>
<td width=698 height=420>
<?=getMapHtml()?>
<?=getMapHtml($mapTheme)?>
</td>
<td width=139 valign=top><div style='background-color:#cccccc;color:black;text-align:center'>국명</div><?=$nationStr?></td>
<td width=70 valign=top style='text-align:center'><div style='background-color:#cccccc;color:black;'>국력</div><?=$powerStr?></td>
+111 -87
View File
@@ -9,8 +9,6 @@ if ($type <= 0 || $type > 8) {
$type = 7;
}
extractMissingPostToGlobals();
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
@@ -19,7 +17,7 @@ $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
increaseRefresh("암행부", 2);
increaseRefresh("암행부", 1);
$query = "select no,nation,level,con,turntime,belong from general where owner='{$userID}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect), "");
@@ -43,6 +41,8 @@ if ($me['level'] == 0 || ($me['level'] == 1 && $me['belong'] < $nation['secretli
$sel = [];
$sel[$type] = "selected";
$templates = new \League\Plates\Engine('templates');
?>
<!DOCTYPE html>
<html>
@@ -54,15 +54,18 @@ $sel[$type] = "selected";
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 암행부</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td>암 행 부<br><?=closeButton()?></td></tr>
<tr><td><form name=form1 method=post>정렬순서 :
<tr><td><form name=form1 method=get>정렬순서 :
<select name=type size=1>
<option <?=$sel[1]??''?> value=1>자금</option>
<option <?=$sel[2]??''?> value=2>군량</option>
@@ -77,54 +80,28 @@ $sel[$type] = "selected";
</td></tr>
</table>
<?php
$query = "select troop,name from troop where nation='{$me['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect), "");
$troopCount = MYDB_num_rows($result);
$troopName = [];
for ($i=0; $i < $troopCount; $i++) {
$troop = MYDB_fetch_array($result);
$troopName[$troop['troop']] = $troop['name'];
foreach($db->queryAllLists('SELECT troop, name FROM troop WHERE nation=%i', $me['nation']) as [$troopID, $tName]){
$troopName[$troopID] = $tName;
}
$orderSQL = '';
switch ($type) {
case 1: $query = "select npc,mode,no,level,troop,city,injury,leader,power,intel,experience,name,gold,rice,crewtype,crew,train,atmos,killturn,turntime,term,turn0,turn1,turn2,turn3,turn4 from general where nation='{$me['nation']}' order by gold desc"; break;
case 2: $query = "select npc,mode,no,level,troop,city,injury,leader,power,intel,experience,name,gold,rice,crewtype,crew,train,atmos,killturn,turntime,term,turn0,turn1,turn2,turn3,turn4 from general where nation='{$me['nation']}' order by rice desc"; break;
case 3: $query = "select npc,mode,no,level,troop,city,injury,leader,power,intel,experience,name,gold,rice,crewtype,crew,train,atmos,killturn,turntime,term,turn0,turn1,turn2,turn3,turn4 from general where nation='{$me['nation']}' order by city"; break;
case 4: $query = "select npc,mode,no,level,troop,city,injury,leader,power,intel,experience,name,gold,rice,crewtype,crew,train,atmos,killturn,turntime,term,turn0,turn1,turn2,turn3,turn4 from general where nation='{$me['nation']}' order by crewtype desc"; break;
case 5: $query = "select npc,mode,no,level,troop,city,injury,leader,power,intel,experience,name,gold,rice,crewtype,crew,train,atmos,killturn,turntime,term,turn0,turn1,turn2,turn3,turn4 from general where nation='{$me['nation']}' order by crew desc"; break;
case 6: $query = "select npc,mode,no,level,troop,city,injury,leader,power,intel,experience,name,gold,rice,crewtype,crew,train,atmos,killturn,turntime,term,turn0,turn1,turn2,turn3,turn4 from general where nation='{$me['nation']}' order by killturn"; break;
case 7: $query = "select npc,mode,no,level,troop,city,injury,leader,power,intel,experience,name,gold,rice,crewtype,crew,train,atmos,killturn,turntime,term,turn0,turn1,turn2,turn3,turn4 from general where nation='{$me['nation']}' order by turntime"; break;
case 8: $query = "select npc,mode,no,level,troop,city,injury,leader,power,intel,experience,name,gold,rice,crewtype,crew,train,atmos,killturn,turntime,term,turn0,turn1,turn2,turn3,turn4 from general where nation='{$me['nation']}' order by troop desc"; break;
case 1: $orderSQL = "order by gold desc"; break;
case 2: $orderSQL = "order by rice desc"; break;
case 3: $orderSQL = "order by city"; break;
case 4: $orderSQL = "order by crewtype desc"; break;
case 5: $orderSQL = "order by crew desc"; break;
case 6: $orderSQL = "order by killturn"; break;
case 7: $orderSQL = "order by turntime"; break;
case 8: $orderSQL = "order by troop desc"; break;
}
$genresult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect), "");
$gencount = MYDB_num_rows($genresult);
?>
<table align=center id='general_list' class='tb_layout bg0'>
<thead>
<tr>
<td width=98 align=center class=bg1>이 름</td>
<td width=98 align=center class=bg1>통무지</td>
<td width=98 align=center class=bg1>부 대</td>
<td width=58 align=center class=bg1>자 금</td>
<td width=58 align=center class=bg1>군 량</td>
<td width=48 align=center class=bg1>도시</td>
<td width=28 align=center class=bg1>守</td>
<td width=58 align=center class=bg1>병 종</td>
<td width=68 align=center class=bg1>병 사</td>
<td width=48 align=center class=bg1>훈련</td>
<td width=48 align=center class=bg1>사기</td>
<td width=148 align=center class=bg1>명 령</td>
<td width=58 align=center class=bg1>삭턴</td>
<td width=58 align=center class=bg1>턴</td>
</tr>
</thead>
<tbody>
<?php
for ($j=0; $j < $gencount; $j++) {
$general = MYDB_fetch_array($genresult);
$city = CityConst::byID($general['city'])->name;
$troop = $troopName[$general['troop']]??'-';
$generals = $db->query('SELECT npc,mode,no,level,troop,city,injury,leader,power,intel,experience,name,gold,rice,crewtype,crew,train,atmos,killturn,turntime,term,turn0,turn1,turn2,turn3,turn4 from general WHERE nation = %i %l', $me['nation'], $orderSQL);
foreach ($generals as &$general) {
$general['cityText'] = CityConst::byID($general['city'])->name;
$general['troopText'] = $troopName[$general['troop']]??'-';
if ($general['level'] == 12) {
$lbonus = $nation['level'] * 2;
@@ -134,81 +111,128 @@ for ($j=0; $j < $gencount; $j++) {
$lbonus = 0;
}
if ($lbonus > 0) {
$lbonus = "<font color=cyan>+{$lbonus}</font>";
$lbonusText = "<font color=cyan>+{$lbonus}</font>";
} else {
$lbonus = "";
$lbonusText = "";
}
$general['lbonus'] = $lbonus;
$general['lbonusText'] = $lbonusText;
if ($general['injury'] > 0) {
$leader = intdiv($general['leader'] * (100 - $general['injury']), 100);
$power = intdiv($general['power'] * (100 - $general['injury']), 100);
$intel = intdiv($general['intel'] * (100 - $general['injury']), 100);
$leader = "<font color=red>{$leader}</font>{$lbonus}";
$leader = "<font color=red>{$leader}</font>{$lbonusText}";
$power = "<font color=red>{$power}</font>";
$intel = "<font color=red>{$intel}</font>";
} else {
$leader = "{$general['leader']}{$lbonus}";
$leader = "{$general['leader']}{$lbonusText}";
$power = "{$general['power']}";
$intel = "{$general['intel']}";
}
$general['leaderText'] = $leader;
$general['powerText'] = $power;
$general['intelText'] = $intel;
$general['expLevelText'] = getExpLevel($general['experience']);
if ($general['npc'] >= 2) {
$name = "<font color=cyan>{$general['name']}</font>";
} elseif ($general['npc'] == 1) {
$name = "<font color=skyblue>{$general['name']}</font>";
} else {
$name = "{$general['name']}";
$name = $general['name'];
}
//TODO: npc 코드를 일원화
$general['nameText'] = $name;
switch ($general['mode']) {
case 0: $mode = "×"; break;
case 1: $mode = "○"; break;
case 2: $mode = "◎"; break;
case 0: $mode = "×"; break;
case 1: $mode = "○"; break;
case 2: $mode = "◎"; break;
}
$general['modeText'] = $mode;
$general['crewtypeText'] = GameUnitConst::byId($general['crewtype'])->name??'-';
echo "
<tr>
<td class='i_name' align=center><span class='t_name'>$name</span><br>Lv <span class='t_explevel'>".getExpLevel($general['experience'])."</span></td>
<td class='i_stat' align=center>{$leader}∥{$power}∥{$intel}</td>
<td class='i_troop' align=center>$troop</td>
<td class='i_gold' align=center>{$general['gold']}</td>
<td class='i_rice' align=center>{$general['rice']}</td>
<td class='i_city' align=center>$city</td>
<td align=center>$mode</td>
<td class='i_crewtype' align=center>".GameUnitConst::byId($general['crewtype'])->name."</td>
<td class='i_crew' align=center>{$general['crew']}</td>
<td class='i_train' align=center>{$general['train']}</td>
<td class='i_atmos' align=center>{$general['atmos']}</td>";
if ($general['npc'] >= 2) {
echo "
<td class='i_action'>
<font size=3>NPC 장수";
} else {
echo "
<td class='i_action'>
<font size=1>";
if ($general['npc'] < 2) {
$turntext = [];
$turn = getTurn($general, 1, 0);
for ($i=0; $i < 5; $i++) {
$turn[$i] = StringUtil::subStringForWidth($turn[$i], 0, 20);
$turn[$i] = StringUtil::subStringForWidth($turn[$i], 0, 41);
$k = $i+1;
echo "
&nbsp;$k : $turn[$i] <br>";
$turntext[] = "&nbsp;$k : $turn[$i]";
}
$general['turntext'] = join("<br>\n", $turntext);
}
echo "
</font>
</td>
<td align=center>{$general['killturn']}</td>
<td class='i_turntime' align=center>".substr($general['turntime'], 14, 5)."</td>
</tr>";
}
echo "
unset($general);
$genCnt = count($generals);
$totalGold = 0;
$totalRice = 0;
$crew90 = 0;
$gen90 = 0;
$crew80 = 0;
$gen80 = 0;
$crew60 = 0;
$gen60 = 0;
$crewTotal = 0;
//$genTotal = 0;
foreach($generals as $general){
$totalGold += $general['gold'];
$totalRice += $general['rice'];
$crewTotal += $general['crew'];
if($general['crew'] == 0){
continue;
}
if($general['train'] >= 90 && $general['atmos'] >= 90){
$crew90 += $general['crew'];
$gen90 += 1;
}
if($general['train'] >= 80 && $general['atmos'] >= 80){
$crew80 += $general['crew'];
$gen80 += 1;
}
if($general['train'] >= 60 && $general['atmos'] >= 60){
$crew60 += $general['crew'];
$gen60 += 1;
}
}
?>
<table style='width:1000px;margin:5px auto' class='tb_layout bg0'>
<thead>
<colgroup>
<col style="width:120px;"><col>
<col style="width:120px;"><col>
<col style="width:120px;"><col>
<col style="width:120px;"><col>
</colgroup>
</thead>
<tbody>
<tr>
<td class='bg1'>전체 금</td><td><?=number_format($totalGold)?></td>
<td class='bg1'>전체 쌀</td><td><?=number_format($totalRice)?></td>
<td class='bg1'>평균 금</td><td><?=number_format($totalGold/$genCnt, 2)?></td>
<td class='bg1'>평균 쌀</td><td><?=number_format($totalRice/$genCnt, 2)?></td>
</tr>
<tr>
<td class='bg1'>전체 병력/장수</td><td><?=number_format($crewTotal)?>/<?=number_format($genCnt)?></td>
<td class='bg1'>훈사 90 병력/장수</td><td><?=number_format($crew90)?>/<?=number_format($gen90)?></td>
<td class='bg1'>훈사 80 병력/장수</td><td><?=number_format($crew80)?>/<?=number_format($gen80)?></td>
<td class='bg1'>훈사 60 병력/장수</td><td><?=number_format($crew60)?>/<?=number_format($gen60)?></td>
</tr>
</tbody>
</table>
";
?>
<?=$templates->render('generalList', ['generals'=>$generals])?>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=closeButton()?></td></tr>
+6 -2
View File
@@ -40,8 +40,12 @@ $sel = [$type => "selected"];
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 세력장수</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
</head>
@@ -181,8 +185,8 @@ for($j=0; $j < $gencount; $j++) {
<td align=center>$intel</td>
<td align=center>{$general['gold']}</td>
<td align=center>{$general['rice']}</td>
<td align=center>".getGenChar($general['personal'])."</td>
<td align=center>".getGenSpecial($general['special'])." / ".getGenSpecial($general['special2'])."</td>
<td align=center>".displayCharInfo($general['personal'])."</td>
<td align=center>".displaySpecialInfo($general['special'])." / ".displaySpecialInfo($general['special2'])."</td>
<td align=center>{$general['belong']}</td>
<td align=center>{$general['connect']}"; echo "<br>(".getConnect($general['connect']).")</td>
</tr>";
+4
View File
@@ -81,6 +81,10 @@ if (($btn == "설정저장" || $detachNPC) && $me['myset'] > 0) {
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 내정보</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
+122 -99
View File
@@ -12,13 +12,58 @@ $connect=$db->get();
increaseRefresh("부대편성", 1);
$query = "select no,nation,troop from general where owner='{$userID}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$me = MYDB_fetch_array($result);
$me = $db->queryFirstRow('SELECT no,nation,troop FROM general WHERE owner=%i', $userID);
$query = "select * from troop where nation='{$me['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$troopcount = MYDB_num_rows($result);
$troops = [];
foreach($db->query('SELECT troop,name,no FROM troop WHERE nation = %i', $me['nation']) as $rawTroop){
$troops[$rawTroop['troop']] = [
'troop'=>$rawTroop['troop'],
'name'=>$rawTroop['name'],
'no'=>$rawTroop['no'],
'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){
foreach($db->query(
'SELECT no,name,picture,imgsvr,turntime,city,turn0,turn1,turn2,turn3,turn4,turn5,troop FROM general WHERE no IN %li',
array_column($troops, 'no')
) as $troopLeader
){
$imageTemp = GetImageURL($troopLeader['imgsvr']);
$troopLeader['pictureFullPath'] = "$imageTemp/{$troopLeader['picture']}";
$troopLeader['cityText'] = CityConst::byID($troopLeader['city'])->name;
$troopLeader['turnText'] = join('<br>', [
'1 : '.((DecodeCommand($troopLeader['turn0'])[0] == 26)?'집합':'~'),
'2 : '.((DecodeCommand($troopLeader['turn1'])[0] == 26)?'집합':'~'),
'3 : '.((DecodeCommand($troopLeader['turn2'])[0] == 26)?'집합':'~'),
'4 : '.((DecodeCommand($troopLeader['turn3'])[0] == 26)?'집합':'~'),
'5 : '.((DecodeCommand($troopLeader['turn4'])[0] == 26)?'집합':'~'),
]);
$troops[$troopLeader['troop']]['leader'] = $troopLeader;
}
}
uasort($troops, function($lhs, $rhs){
return $lhs['leader']['turntime']<=>$rhs['leader']['turntime'];
})
?>
<!DOCTYPE html>
@@ -30,6 +75,7 @@ $troopcount = MYDB_num_rows($result);
<title><?=UniqueConst::$serverName?>: 부대편성</title>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/troops.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('js/ext.plugin_troop.js')?>
</head>
@@ -50,120 +96,97 @@ $troopcount = MYDB_num_rows($result);
<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=submit name=btn value='부 대 가 입'>
<?php else: ?>
<input type=submit name=btn value='부 대 탈 퇴' onclick='return confirm(\"정말 부대를 탈퇴하시겠습니까?\")'>
<?php endif;?>
</td></tr></tfoot>
<tbody>
<?php
for($i=0; $i < $troopcount; $i++) {
$troop = MYDB_fetch_array($result);
foreach ($troops as $troopNo=>$troop) {
$troopLeader = $troop['leader'];
$genlistText = [];
$cityText = $troopLeader['cityText'];
$cityID = $troopLeader['city'];
$leaderID = $troopLeader['no'];
$genlist = "";
$query = "select no,name,picture,imgsvr,turntime,city,turn0,turn1,turn2,turn3,turn4,turn5 from general where troop='{$troop['troop']}'";
$genresult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$gencount = MYDB_num_rows($genresult);
for($j=0; $j < $gencount; $j++) {
$general = MYDB_fetch_array($genresult);
$genlist .= $general['name'].", ";
if($troop['no'] == $general['no']) {
$picture = $general['picture'];
$imageTemp = GetImageURL($general['imgsvr']);
$name = $general['name'];
$turntime = $general['turntime'];
$query = "select name from city where city='{$general['city']}'";
$cityresult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$city = MYDB_fetch_array($cityresult);
$cityname = $city['name'];
$turn = "";
for($k=0; $k < 5; $k++) {
$m = $k+1;
if($general["turn{$k}"] == 26) {
$turn .= "&nbsp;$m : 집합<br>";
} else {
$turn .= "&nbsp;$m : <br>";
}
}
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>";
}
$genlist .= "({$gencount}명)";
if($me['troop'] == 0) {
echo "
$genlistText = sprintf('%s (%d명)', join(', ', $genlistText), count($genlistText)); ?>
<?php if ($me['troop'] == 0): ?>
<tr>
<td align=center rowspan=2><input "; echo $i==0?"checked ":""; echo "type=radio name=troop value='{$troop['troop']}'></td>
<td align=center >{$troop['name']}<br>【 $cityname 】</td>
<td height=64 style='background:no-repeat center url(\"{$imageTemp}/{$picture}\");background-size:64px;'>&nbsp;</td>
<td rowspan=2 width=62>$genlist</td>
<td rowspan=2>$turn</td>
<td align=center rowspan=2><input type='radio' name='troop' value='<?=$troop['troop']?>'></td>
<td align=center><?=$troop['name']?><br>【 <?=$cityText?> 】</td>
<td height=64 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($turntime, 14)."</font></td><td align=center><font size=1>$name</font></td></tr>
<tr><td colspan=5>";
} else {
echo "
<tr>
<td align=center><font size=2>【턴】 <?=substr($troopLeader['turntime'], 14)?></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>【 $cityname 】</td>
<td height=64 style='background:no-repeat center url(\"{$imageTemp}/{$picture}\");background-size:64px;'>&nbsp;</td>
<td rowspan=2 width=576>$genlist</td>
<td rowspan=2>";
if($troop['no'] == $me['no']) {
$query = "select no,name from general where troop='{$troop['troop']}' and no!='{$me['no']}' order by binary(name)";
$genresult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$genCount = MYDB_num_rows($genresult);
echo "
<td align=center ><?=$troop['name']?><br>【 <?=$cityText?> 】</td>
<td height=64 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 name=gen size=3 style=color:white;background-color:black;font-size:13px;width:128px;>";
for($k=0; $k < $genCount; $k++) {
$general = MYDB_fetch_array($genresult);
echo "
<option value={$general['no']}>{$general['name']}</option>";
}
echo "
<?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=submit name=btn value='부 대 추 방' style=width:130px;height:25px;>";
} else {
echo $turn;
}
echo "
<input type=submit name=btn value='부 대 추 방' style=width:130px;height:25px;>
<?php else: ?>
<?=$troopLeader['turnText']?>
<?php endif; ?>
</td>
</tr>
<tr><td align=center><font size=2>【턴】".substr($turntime, 14)."</font></td><td align=center><font size=1>$name</font></td></tr>
<tr><td colspan=5>";
}
}
echo "</tbody>
<tfoot>";
if ($troopcount == 0) {
}
else if($me['troop'] == 0) {
echo"
<input type=submit name=btn value='부 대 가 입'>";
} else {
echo"
<input type=submit name=btn value='부 대 탈 퇴' onclick='return confirm(\"정말 부대를 탈퇴하시겠습니까?\")'>";
}
<tr><td align=center><font size=2>【턴】 <?=substr($troopLeader['turntime'], 14)?></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>
echo "
</td></tr>
</tfoot>
</table>
<br>";
echo "
<br>
<table width=1000 class='tb_layout bg0'>
<tr>
<td width=80 id=bg1>부 대 명</td>
<td width=130><input type=text style=color:white;background-color:black; size=18 maxlength=9 name=name></td>";
if($me['troop'] == 0) {
echo "
<td><input type=submit name=btn value='부 대 창 설'></td>";
} else {
echo "
<td><input type=submit name=btn value='부 대 변 경'></td>";
}
echo "
<td width=130><input type=text style=color:white;background-color:black; size=18 maxlength=9 name=name></td>
<?php if($me['troop'] == 0): ?>
<td><input type=submit name=btn value='부 대 창 설'></td>
<?php else: ?>
<td><input type=submit name=btn value='부 대 변 경'></td>
<?php endif; ?>
</tr>
</table>";
</table>
?>
<table width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?> </td></tr>
-1
View File
@@ -37,7 +37,6 @@ if($third < 0) { $third = 0; }
if($fourth < 0) { $fourth = 0; }
if($command > 99) { $command = 0; }
if($double > 9999) { $double = 9999; }
if($third > 9999) { $third = 9999; }
if($fourth > 9999) { $fourth = 9999; }
$comStr = EncodeCommand($fourth, $third, $double, $command);
+20 -3
View File
@@ -134,8 +134,25 @@ if($btn == "추방") {
$log[] = "<C>●</><D><b>{$nation['name']}</b></>에서 <R>추방</>당하였습니다.";
// 재야로, 국가 무소속으로, 명성/공헌 N*10%감소
$query = "update general set level=0,nation=0,belong=0,betray=betray+1,makelimit='12',gold='{$general['gold']}',rice='{$general['rice']}',dedication=dedication*(1-0.1*betray),experience=experience*(1-0.1*betray) where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
if($admin['year'] <= $admin['startyear'] && $general['npc'] < 2){
$db->update('general', [
'level'=>0,
'nation'=>0,
'belong'=>0,
], 'no=%i', $general['no']);
}
else{
$db->update('general', [
'level'=>0,
'nation'=>0,
'belong'=>0,
'betray'=>$db->sqleval('betray + 1'),
'makelimit'=>12,
'gold'=>$general['gold'],
'rice'=>$general['rice'],
'dedication'=>$db->sqleval('dedication * (1 - 0.1*betray)'),
], 'no=%i', $general['no']);
}
}
// 부대 처리
$query = "select no from troop where troop='{$general['troop']}'";
@@ -163,7 +180,7 @@ if($btn == "추방") {
$query = "update city set gen3='0' where gen3='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
if($general['npc'] >= 2 && ($admin['scenario'] == 0 || rand()%100 == 0)) {
if($general['npc'] >= 2 && ($admin['scenario'] < 100 || rand()%100 == 0)) {
switch(rand()%5) {
case 0: $str = "날 버리다니... 곧 전장에서 복수해주겠다..."; break;
case 1: $str = "추방이라... 내가 무얼 잘못했단 말인가..."; break;
+7 -3
View File
@@ -38,9 +38,13 @@ case 3: $tp = "intel"; $tp2 = "설전"; $tp3 = "intel"; break;
}
if($btn == '참가') {
$query = "select no,name,npc,leader,power,intel,explevel,gold,horse,weap,book from general where no='{$me['no']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$general = MYDB_fetch_array($result);
if($db->queryFirstField('SELECT `no` FROM tournament WHERE `no`=%i', $me['no'])){
header('location:b_tournament.php');
exit(1);
}
$general = $db->queryFirstRow('SELECT no,name,npc,leader,power,intel,explevel,gold,horse,weap,book FROM general WHERE `no`=%i', $me['no']);
//{$admin['develcost']}원 참가비
if($general['gold'] < $admin['develcost']) {
+10 -31
View File
@@ -188,38 +188,17 @@ div.bar_out div.bar_in{
}
.tooltip{
position: relative;
font-size:12px;
font-family: '맑은 고딕';
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -60px;
opacity: 0;
transition: opacity 0.3s;
.tooltiptext {
display: none;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
.btn-group-xs > .btn, .btn-xs {
padding : .25rem .4rem;
font-size : .875rem;
line-height : .5;
border-radius : .2rem;
}
+57 -3
View File
@@ -27,12 +27,51 @@
position:relative;
}
.map_body .map_bglayer1{
width:100%;
height:100%;
position:absolute;
left:0;
top:0;
}
.map_body .map_bglayer2{
width:100%;
height:100%;
position:absolute;
left:0;
top:0;
}
.map_body .map_bgroad{
width:100%;
height:100%;
position:absolute;
left:0;
top:0;
}
.map_body .map_button_stack{
position:absolute;
right:0;
bottom:0;
}
.map_body .map_toggle_cityname::after{
content: "끄기"
}
.map_body .map_toggle_cityname.active::after{
content: "켜기"
}
.world_map .city_tooltip{
position: absolute;
z-index:6;
display:none;
width:120px;
min-width:120px;
border: 0.02em gray solid;
white-space: nowrap;
}
.world_map .city_name{
background-color: rgb(30, 164, 255);
@@ -63,13 +102,26 @@
.world_map.map_detail .city_filler{
position:absolute;
width:100%;
height:100%;
width:calc(100% + 2px);
height:calc(100% + 2px);
left:-1px;
top:-1px;
background:transparent;
}
.world_map .city_detail_name{
background-color:rgba(0,0,0,0.5);
font-size:10px;
position:absolute;
white-space:nowrap;
left:70%;
bottom:-10px;
color:white;
}
.world_map.hide_cityname .city_detail_name{
display:none;
}
.city_base{
position:absolute;
@@ -314,6 +366,8 @@
/* Basic */
.world_map.map_basic .city_filler{
position:absolute;
width:100%;
+13 -11
View File
@@ -17,15 +17,14 @@
#message_board section{
overflow-y:auto;
overflow-x:hidden;
max-width:498px;
}
.msg_plate{
width:100%;
border-bottom:solid 1px gray;
border-left:solid 1px gray;
border-right:solid 1px gray;
height:64px;
outline-style:solid;
outline-width:1px;
outline-color: gray;
min-height:64px;
font-size:12px;
word-break:break-all;
color:white;
@@ -96,7 +95,8 @@
font-size:12px;
width:715px;
margin:0 2px;
height:15px;
height:20px;
border:solid 1px gray;
}
#msg_submit{
@@ -116,17 +116,19 @@
.board_header{
color:white;
border:solid 1px gray;
outline-style:solid;
outline-width:1px;
outline-color: gray;
}
.board_side{
position:absolute;
height:1370px;
width:498px;
width:50%;
overflow-y: hidden;
border-left:solid 1px;
border-right:solid 1px;
border-bottom:solid 1px;
outline-style:solid;
outline-width:1px;
outline-color: gray;
}
.msg_body{
+23
View File
@@ -0,0 +1,23 @@
#troop_list .cityText{
display:none;
}
#troop_list .diffCity .cityText{
display:inline;
}
#troop_list .diffCity {
color:red;
}
#troop_list .leader{
color:lightgreen;
}
#troop_list .leader::before{
content:'*';
}
#troop_list .leader::after{
content:'*';
}
+7
View File
@@ -0,0 +1,7 @@
<?php
namespace sammo;
class CityConst extends CityConstBase{
}
+6
View File
@@ -0,0 +1,6 @@
<?php
namespace sammo;
class GameConst extends GameConstBase
{
}
-12
View File
@@ -1,12 +0,0 @@
<?php
namespace sammo;
class GameCustomConst
{
/** @var int 유저 스탯 총합 */
public static $defaultStatTotal = _tK_statTotal_;
public static $defaultStatMin = _tK_statMin_;
public static $defaultStatMax = _tK_statMax_;
public static $defaultStatNPCMax = _tK_statNPCMax_;
public static $chiefStatMin = _tK_statChiefMin_;
}
+6
View File
@@ -0,0 +1,6 @@
<?php
namespace sammo;
class GameUnitConst extends GameUnitConstBase
{
}
+1
View File
@@ -0,0 +1 @@
Deny from all
+144 -16
View File
@@ -424,7 +424,7 @@ function addCommand($typename, $value, $valid = 1, $color=0) {
function commandGroup($typename, $type=0) {
if($type == 0) {
echo "
<optgroup label='{$typename}' style=color:skyblue;background-color:black;>";
<optgroup label='{$typename}' style='color:skyblue;background-color:black;'>";
} else {
echo "
</optgroup>";
@@ -490,7 +490,7 @@ function commandTable() {
$develcostE = Util::round($develcostE);
echo "
<select name=commandtype size=1 style=width:260px;color:white;background-color:black;font-size:12px;>";
<select name=commandtype size=1 style='height:20px;width:260px;color:white;background-color:black;font-size:12px;'>";
addCommand("휴 식", 0);
addCommand("요 양", 50);
commandGroup("========= 내 정 ==========");
@@ -524,7 +524,7 @@ function commandTable() {
addCommand("첩보(통솔경험, 자금$develcost3, 군량$develcost3)", 31);
addCommand("징병(통솔경험)", 11);
addCommand("모병(통솔경험, 자금x2)", 12);
addCommand("훈련(통솔경험, 사기↓)", 13);
addCommand("훈련(통솔경험)", 13);
addCommand("사기진작(통솔경험, 자금↓)", 14);
//addCommand("전투태세/3턴(통솔경험, 자금↓)", 15);
addCommand("출병", 16);
@@ -532,7 +532,7 @@ function commandTable() {
addCommand("첩보(통솔경험, 자금$develcost3, 군량$develcost3)", 31, 0);
addCommand("징병(통솔경험)", 11, 0);
addCommand("모병(통솔경험, 자금x2)", 12, 0);
addCommand("훈련(통솔경험, 사기↓)", 13, 0);
addCommand("훈련(통솔경험)", 13, 0);
addCommand("사기진작(통솔경험, 자금↓)", 14, 0);
//addCommand("전투태세/3턴(통솔경험, 자금↓)", 15, 0);
addCommand("출병", 16, 0);
@@ -699,7 +699,8 @@ function CoreCommandTable() {
if($city['supply'] == 0) { $valid = 0; }
echo "
<select name=commandtype size=1 style=color:white;background-color:black;font-size:13>";
<select name=commandtype size=1 style='height:20px;color:white;background-color:black;font-size:13px;'>";
commandGroup("====== 휴 식 ======");
addCommand("휴 식", 99);
commandGroup("", 1);
commandGroup("====== 인 사 ======");
@@ -821,7 +822,7 @@ function generalInfo($no) {
$weapname = getWeapName($general['weap']);
$bookname = getBookName($general['book']);
$horsename = getHorseName($general['horse']);
$itemname = getItemName($general['item']);
$itemname = displayItemInfo($general['item']);
if($general['injury'] > 0) {
$leader = intdiv($general['leader'] * (100 - $general['injury']), 100);
$power = intdiv($general['power'] * (100 - $general['injury']), 100);
@@ -847,8 +848,8 @@ function generalInfo($no) {
else { $general['age'] = "<font color=red>{$general['age']} 세</font>"; }
$general['connect'] = Util::round($general['connect'] / 10) * 10;
$special = $general['special'] == 0 ? "{$general['specage']}" : "<font color=limegreen>".getGenSpecial($general['special'])."</font>";
$special2 = $general['special2'] == 0 ? "{$general['specage2']}" : "<font color=limegreen>".getGenSpecial($general['special2'])."</font>";
$special = $general['special'] == 0 ? "{$general['specage']}" : "<font color=limegreen>".displaySpecialInfo($general['special'])."</font>";
$special2 = $general['special2'] == 0 ? "{$general['specage2']}" : "<font color=limegreen>".displaySpecialInfo($general['special2'])."</font>";
switch($general['personal']) {
case 2: case 4:
@@ -913,7 +914,7 @@ function generalInfo($no) {
<td style='text-align:center;' class='bg1'><b>병사</b></td>
<td style='text-align:center;' colspan=2>{$general['crew']}</td>
<td style='text-align:center;' class='bg1'><b>성격</b></td>
<td style='text-align:center;' colspan=2>".getGenChar($general['personal'])."</td>
<td style='text-align:center;' colspan=2>".displayCharInfo($general['personal'])."</td>
</tr>
<tr>
<td style='text-align:center;' class='bg1'><b>훈련</b></td>
@@ -1128,7 +1129,7 @@ function msgprint($msg, $name, $picture, $imgsvr, $when, $num, $type) {
$db = DB::db();
$connect=$db->get();
$message = explode("|", $msg);
$message = explode('|', $msg);
$count = (count($message) - 2)/2;
$message[0] = Tag2Code($message[0]);
$message[1] = Tag2Code($message[1]);
@@ -1180,11 +1181,10 @@ function msgprint($msg, $name, $picture, $imgsvr, $when, $num, $type) {
function banner() {
return sprintf(
'<font size=2>%s %s / %s <br> %s</font>',
'<font size=2>%s %s / %s</font>',
GameConst::$title,
VersionGit::$version,
GameConst::$banner,
GameConst::$helper);
GameConst::$banner);
}
function addTurn($date, int $turnterm, int $turn=1) {
@@ -1871,7 +1871,7 @@ function PreprocessCommand($no) {
$josaUl = JosaUtil::pick($general['item'], '을');
$log[0] = "<C>●</><C>".getItemName($general['item'])."</>{$josaUl} 사용하여 치료합니다!";
pushGenLog($general, $log);
} elseif($general['injury'] > 10 && $general['item'] == 1 && $general['turn0'] != EncodeCommand(0, 0, 0, 50)) {
} elseif($general['injury'] > 10 && $general['item'] == 1 && DecodeCommand($general['turn0'])[0] != 50) {
//환약 사용
$query = "update general set injury=0,item=0 where no='$no'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
@@ -2017,7 +2017,7 @@ function updateTurntime($no) {
default: $alllog[0] = "<C>●</>{$admin['month']}월:<Y>{$general['name']}</>{$josaYi} <R>사망</>했습니다."; break;
}
// 엔피씨,엠피씨,의병 사망로그
if($general['npc'] == 2) {
if($general['npc'] == 2 || $general['npc'] == 6) {
$alllog[0] = "<C>●</>{$admin['month']}월:<Y>{$general['name']}</>{$josaYi} <R>사망</>했습니다.";
} elseif($general['npc'] >= 3) {
switch(rand()%10) {
@@ -2167,6 +2167,7 @@ function CheckHall($no) {
function uniqueItem($general, $log, $vote=0) {
//TODO: uniqueItem 재 구현
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
@@ -2184,7 +2185,7 @@ function uniqueItem($general, $log, $vote=0) {
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$gen = MYDB_fetch_array($result);
if($admin['scenario'] == 0) { $prob = $gen['cnt'] * 5; } // 5~6개월에 하나씩 등장
if($admin['scenario'] < 100) { $prob = $gen['cnt'] * 5; } // 5~6개월에 하나씩 등장
else { $prob = $gen['cnt']; } // 1~2개월에 하나씩 등장
if($vote == 1) { $prob = Util::round($gen['cnt'] * 0.7 / 3); } // 투표율 70%, 투표 한번에 2~3개 등장
@@ -2295,6 +2296,69 @@ function uniqueItem($general, $log, $vote=0) {
return $log;
}
function checkAbilityEx(int $generalID, ActionLogger $actLog){
$db = DB::db();
$general = $db->queryFirstRow('SELECT leader,leader2,power,power2,intel,intel2 FROM general WHERE no = %i',$generalID);
if(!$general){
return;
}
if($general['leader2'] < 0){
$db->update('general',[
'leader2'=>$db->sqleval('leader2 + %i', GameConst::$upgradeLimit),
'leader'=>$db->sqleval('leader - 1')
], 'no=%i', $generalID);
$actLog->pushGeneralActionLog('<R>통솔</>이 <C>1</> 떨어졌습니다!', ActionLogger::PLAIN);
return;
}
if($general['power2'] < 0){
$db->update('general',[
'power2'=>$db->sqleval('power2 + %i', GameConst::$upgradeLimit),
'power'=>$db->sqleval('power - 1')
], 'no=%i', $generalID);
$actLog->pushGeneralActionLog('<R>무력</>이 <C>1</> 떨어졌습니다!', ActionLogger::PLAIN);
return;
}
if($general['intel2'] < 0){
$db->update('general',[
'intel2'=>$db->sqleval('intel2 + %i', GameConst::$upgradeLimit),
'intel'=>$db->sqleval('intel - 1')
], 'no=%i', $generalID);
$actLog->pushGeneralActionLog('<R>지력</>이 <C>1</> 떨어졌습니다!', ActionLogger::PLAIN);
return;
}
if($general['leader2'] >= GameConst::$upgradeLimit){
$db->update('general',[
'leader2'=>$db->sqleval('leader2 - %i', GameConst::$upgradeLimit),
'leader'=>$db->sqleval('leader + 1')
], 'no=%i', $generalID);
$actLog->pushGeneralActionLog('<R>통솔</>이 <C>1</> 올랐습니다!', ActionLogger::PLAIN);
return;
}
if($general['power2'] >= GameConst::$upgradeLimit){
$db->update('general',[
'power2'=>$db->sqleval('power2 - %i', GameConst::$upgradeLimit),
'power'=>$db->sqleval('power + 1')
], 'no=%i', $generalID);
$actLog->pushGeneralActionLog('<R>무력</>이 <C>1</> 올랐습니다!', ActionLogger::PLAIN);
return;
}
if($general['intel2'] >= GameConst::$upgradeLimit){
$db->update('general',[
'intel2'=>$db->sqleval('intel2 - %i', GameConst::$upgradeLimit),
'intel'=>$db->sqleval('intel + 1')
], 'no=%i', $generalID);
$actLog->pushGeneralActionLog('<R>지력</>이 <C>1</> 올랐습니다!', ActionLogger::PLAIN);
return;
}
}
function checkAbility($general, $log) {
$db = DB::db();
$connect=$db->get();
@@ -2601,6 +2665,9 @@ function searchDistance(int $from, int $maxDist=99, bool $distForm = false) {
}
function isNeighbor(int $nation1, int $nation2, bool $includeNoSupply=true) {
if($nation1 === $nation2){
return false;
}
$db = DB::db();
$nation1Cities = [];
@@ -2639,6 +2706,60 @@ function CharExperience($exp, $personal) {
return $exp;
}
function getCharExpMultiplier($personal):float{
static $table = [
0 => 1.1,
1 => 1.1,
4 => 0.9,
5 => 0.9,
6 => 1.1,
7 => 0.9,
10 => 0.9
];
return $table[$personal] ?? 1;
}
function getNationTechMultiplier($nationType):float{
static $table = [
3 => 1.1,
5 => 0.9,
6 => 0.9,
7 => 0.9,
8 => 0.9,
12 => 0.9,
13 => 1.1,
];
return $table[$nationType] ?? 1;
}
function getNationWallMultiplier($nationType):float{
static $table = [
3 => 1.1,
5 => 1.1,
10 => 1.1,
11 => 1.1,
4 => 0.9,
7 => 0.9,
8 => 0.9,
13 => 0.9,
];
return $table[$nationType] ?? 1;
}
function getNationPeopleMultiplier($nationType):float{
static $table = [
1 => 0.9,
2 => 1.1,
3 => 0.9,
4 => 1.1,
7 => 1.1,
9 => 0.9,
10 => 1.1,
];
return $table[$nationType] ?? 1;
}
function CharDedication($ded, $personal) {
switch($personal) {
case 10:
@@ -2649,6 +2770,13 @@ function CharDedication($ded, $personal) {
return $ded;
}
function getCharDedMultiplier($personal):float{
static $table = [
10 => 0.9
];
return $table[$personal] ?? 1;
}
function CharAtmos($atmos, $personal) {
switch($personal) {
case 2: case 4:
+8 -17
View File
@@ -471,7 +471,7 @@ function processCommand($no) {
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
$query = "select npc,no,name,picture,imgsvr,nation,nations,city,troop,injury,affinity,leader,leader2,power,power2,intel,intel2,experience,dedication,level,gold,rice,crew,crewtype,train,atmos,weap,book,horse,item,turntime,makenation,makelimit,killturn,block,dedlevel,explevel,age,belong,personal,special,special2,term,turn0,dex0,dex10,dex20,dex30,dex40 from general where no='$no'";
$query = "select npc,no,name,picture,imgsvr,nation,nations,city,troop,injury,affinity,leader,leader2,power,power2,intel,intel2,experience,dedication,level,gold,rice,crew,crewtype,train,atmos,weap,book,horse,item,turntime,makenation,makelimit,killturn,block,dedlevel,explevel,age,belong,personal,special,special2,term,turn0,dex0,dex10,dex20,dex30,dex40,warnum,killnum,deathnum,killcrew,deathcrew,recwar from general where no='$no'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$general = MYDB_fetch_array($result);
@@ -533,7 +533,7 @@ function processCommand($no) {
}
//장수정보 재로드
$query = "select npc,no,name,picture,imgsvr,nation,nations,city,troop,injury,affinity,leader,leader2,power,power2,intel,intel2,experience,dedication,level,gold,rice,crew,crewtype,train,atmos,weap,book,horse,item,turntime,makenation,makelimit,killturn,block,dedlevel,explevel,age,belong,personal,special,special2,term,turn0,dex0,dex10,dex20,dex30,dex40 from general where no='$no'";
$query = "select npc,no,name,picture,imgsvr,nation,nations,city,troop,injury,affinity,leader,leader2,power,power2,intel,intel2,experience,dedication,level,gold,rice,crew,crewtype,train,atmos,weap,book,horse,item,turntime,makenation,makelimit,killturn,block,dedlevel,explevel,age,belong,personal,special,special2,term,turn0,dex0,dex10,dex20,dex30,dex40,warnum,killnum,deathnum,killcrew,deathcrew,recwar from general where no='$no'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$general = MYDB_fetch_array($result);
}
@@ -628,7 +628,7 @@ function updateCommand($no, $type=0) {
update general set
turn0=turn1,turn1=turn2,turn2=turn3,turn3=turn4,turn4=turn5,turn5=turn6,turn6=turn7,turn7=turn8,turn8=turn9,
turn9=turn10,turn10=turn11,turn11=turn12,turn12=turn13,turn13=turn14,turn14=turn15,turn15=turn16,turn16=turn17,
turn17=turn18,turn18=turn19,turn19=turn20,turn20=turn21,turn21=turn22,turn22=turn23,turn23='00000000000000'
turn17=turn18,turn18=turn19,turn19=turn20,turn20=turn21,turn21=turn22,turn22=turn23,turn23='".EncodeCommand(0, 0, 0, 0)."'
where no='{$general['no']}'
";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
@@ -642,7 +642,7 @@ update nation set
{$turn}4={$turn}5,{$turn}5={$turn}6,
{$turn}6={$turn}7,{$turn}7={$turn}8,
{$turn}8={$turn}9,{$turn}9={$turn}10,
{$turn}10={$turn}11,{$turn}11='00000000000099'
{$turn}10={$turn}11,{$turn}11='".EncodeCommand(0, 0, 0, 99)."'
where nation='{$general['nation']}'
";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
@@ -672,7 +672,7 @@ turn9=turn8,turn8=turn7,
turn7=turn6,turn6=turn5,
turn5=turn4,turn4=turn3,
turn3=turn2,turn2=turn1,
turn1=turn0,turn0='00000000000000'
turn1=turn0,turn0='".EncodeCommand(0, 0, 0, 0)."'
where no='$no'
";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
@@ -685,7 +685,7 @@ update nation set
{$turn}7={$turn}6,{$turn}6={$turn}5,
{$turn}5={$turn}4,{$turn}4={$turn}3,
{$turn}3={$turn}2,{$turn}2={$turn}1,
{$turn}1={$turn}0,{$turn}0='00000000000099'
{$turn}1={$turn}0,{$turn}0='".EncodeCommand(0, 0, 0, 99)."'
where nation='{$general['nation']}'
";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
@@ -772,19 +772,10 @@ parent.moveProcessing(<?=$commandtype?>, <?=Json::encode($turn)?>);
function EncodeCommand($fourth, $third, $double, $command) {
$str = StringUtil::padStringAlignRight((string)$fourth, 4, "0");
$str .= StringUtil::padStringAlignRight((string)$third, 4, "0");
$str .= StringUtil::padStringAlignRight((string)$double, 4, "0");
$str .= StringUtil::padStringAlignRight((string)$command, 2, "0");
return $str;
return Json::encode([$command, $double, $third, $fourth]);
}
function DecodeCommand($str) {
$command = [];
$command[3] = (int)(substr($str, 0, 4));
$command[2] = (int)(substr($str, 4, 4));
$command[1] = (int)(substr($str, 8, 4));
$command[0] = (int)(substr($str, 12, 2));
return $command;
return Json::decode($str);
}
+176 -119
View File
@@ -135,6 +135,28 @@ function getGenChar($type) {
return $call;
}
function getCharInfo(?int $type):?string {
if($type === null){
return null;
}
$infoText = [
10=>['은둔', '명성 -10%, 계급 -10%, 사기 -5, 훈련 -5, 단련 성공률 +10%'],
9=>['안전', '사기 -5, 징·모병 비용 -20%'],
8=>['유지', '훈련 -5, 징·모병 비용 -20%'],
7=>['재간', '명성 -10%, 징·모병 비용 -20%'],
6=>['출세', '명성 +10%, 징·모병 비용 +20%'],
5=>['할거', '명성 -10%, 훈련 +5'],
4=>['정복', '명성 -10%, 사기 +5'],
3=>['패권', '훈련 +5, 징·모병 비용 +20%'],
2=>['의협', '사기 +5, 징·모병 비용 +20%'],
1=>['대의', '명성 +10%, 훈련 -5'],
0=>['왕좌', '명성 +10%, 사기 -5'],
];
return $infoText[$type][1]??null;
}
function getGenSpecial($type) {
switch($type) {
case 0: $call = '-'; break;
@@ -179,6 +201,55 @@ function getGenSpecial($type) {
return $call;
}
function getSpecialInfo(?int $type):?string{
if($type === null){
return null;
}
//앞칸은 '설명을 위해' '그냥' 적어둠
$infoText = [
0 => ['-', null],
1 => ['경작', '[내정] 농지 개간 : 기본 보정 +10%, 성공률 +10%p, 비용 -20%'],
2 => ['상재', '[내정] 상업 투자 : 기본 보정 +10%, 성공률 +10%p, 비용 -20%'],
3 => ['발명', '[내정] 기술 연구 : 기본 보정 +10%, 성공률 +10%p, 비용 -20%'],
10 => ['축성', '[내정] 성벽 보수 : 기본 보정 +10%, 성공률 +10%p, 비용 -20%'],
11 => ['수비', '[내정] 수비 강화 : 기본 보정 +10%, 성공률 +10%p, 비용 -20%'],
12 => ['통찰', '[내정] 치안 강화 : 기본 보정 +10%, 성공률 +10%p, 비용 -20%'],
20 => ['인덕', '[내정] 주민 선정·정착 장려 : 기본 보정 +10%, 성공률 +10%p, 비용 -20%'],
30 => ['거상', '이것 저것'],
31 => ['귀모', '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p'],
40 => ['귀병', '[군사] 귀병 계통 징·모병비 -10%<br>[전투] 계략 성공 확률 +20%p'],
41 => ['신산', '[계략] 화계·탈취·파괴·선동 : 성공률 +10%p<br>[전투] 계략 시도 확률 +20%p, 계략 성공 확률 +20%p '],
42 => ['환술', '[전투] 계략 성공 확률 +10%p, 계략 성공 시 대미지 +30%'],
43 => ['집중', '[전투] 계략 성공 시 대미지 +50%'],
44 => ['신중', '[전투] 계략 성공 확률 100%'],
45 => ['반계', '[전투] 상대의 계략을 30% 확률로 되돌림, 반목 성공시 대미지 추가(+60% → +100%)'],
50 => ['보병', '[군사] 보병 계통 징·모병비 -10%<br>[전투] 공격 시 아군 피해 -10%, 수비 시 아군 피해 -20%'],
51 => ['궁병', '[군사] 궁병 계통 징·모병비 -10%<br>[전투] 회피 확률 +20%p'],
52 => ['기병', '[군사] 기병 계통 징·모병비 -10%<br>[전투] 수비 시 대미지 +10%, 공격 시 대미지 +20%'],
53 => ['공성', '[군사] 차병 계통 징·모병비 -10%<br>[전투] 성벽 공격 시 대미지 +100%'],
60 => ['돌격', '[전투] 상대 회피 불가, 공격 시 전투 페이즈 +1, 공격 시 대미지 +10%'],
61 => ['무쌍', '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p'],
62 => ['견고', '[전투] 수비 시 대미지 +10%, 공격 시 아군 피해 -10%'],
63 => ['위압', '[전투] 훈련/사기≥90, 병력≥1,000 일 때 첫 페이즈 위압 발동(적 공격 불가)'],
70 => ['저격', '[전투] 전투 개시 시 1/3 확률로 저격 발동'],
71 => ['필살', '[전투] 필살 확률 +20%p'],
72 => ['징병', '[군사] 징·모병비 -50%'],
73 => ['의술', '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'],
74 => ['격노', '[전투] 상대방 필살 및 회피 시도시 일정 확률로 격노(필살) 발동, 공격 시 일정 확률로 진노(1페이즈 추가)'],
75 => ['척사', '[전투] 지역·도시 병종 상대로 대미지 +10%, 아군 피해 -10%']
];
return $infoText[$type][1]??null;
}
function getNationType($type) {
switch($type) {
case 13: $call = '명 가'; break;
@@ -284,60 +355,43 @@ function getLevel($level, $nlevel=8) {
function getCall($leader, $power, $intel) {
$call = '평범';
if($leader >= GameConst::$chiefStatMin && $power >= GameConst::$chiefStatMin && $intel >= GameConst::$chiefStatMin) {
$call = '만능';
} elseif($leader >= GameConst::$chiefStatMin && $power >= GameConst::$chiefStatMin) {
$call = '용장';
} elseif($leader >= GameConst::$chiefStatMin && $intel >= GameConst::$chiefStatMin) {
$call = '지장';
} elseif($power >= GameConst::$chiefStatMin && $intel >= GameConst::$chiefStatMin) {
$call = '명장';
} elseif($leader >= GameConst::$chiefStatMin) {
$call = '사';
} elseif($power >= GameConst::$chiefStatMin) {
$call = '용맹';
} elseif($intel >= GameConst::$chiefStatMin) {
$call = '현명';
if($leader < 40){
if($power + $intel < $leader){
return '아둔';
}
if($intel >= GameConst::$chiefStatMin && $power < $intel * 0.8){
return '학자';
}
if($power >= GameConst::$chiefStatMin && $intel < $power * 0.8){
return '사';
}
return '명사';
}
return $call;
$maxStat = max($leader, $power, $intel);
$sum2Stat = min($leader+$power, $power+$intel, $intel+$leader);
if($maxStat >= GameConst::$chiefStatMin + GameConst::$statGradeLevel && $sum2Stat >= $maxStat * 1.7){
return '만능';
}
if($power >= GameConst::$chiefStatMin - GameConst::$statGradeLevel && $intel < $power * 0.8){
return '용장';
}
if($intel >= GameConst::$chiefStatMin - GameConst::$statGradeLevel && $power < $intel * 0.8){
return '명장';
}
return '평범';
}
function getDed($dedication) {
if($dedication < 1 ) $level2 = '무품관';
elseif($dedication < 10*10) $level2 = '30품관';
elseif($dedication < 20*20) $level2 = '29품관';
elseif($dedication < 30*30) $level2 = '28품관';
elseif($dedication < 40*40) $level2 = '27품관';
elseif($dedication < 50*50) $level2 = '26품관';
elseif($dedication < 60*60) $level2 = '25품관';
elseif($dedication < 70*70) $level2 = '24품관';
elseif($dedication < 80*80) $level2 = '23품관';
elseif($dedication < 90*90) $level2 = '22품관';
elseif($dedication < 100*100) $level2 = '21품관';
elseif($dedication < 110*110) $level2 = '20품관';
elseif($dedication < 120*120) $level2 = '19품관';
elseif($dedication < 130*130) $level2 = '18품관';
elseif($dedication < 140*140) $level2 = '17품관';
elseif($dedication < 150*150) $level2 = '16품관';
elseif($dedication < 160*160) $level2 = '15품관';
elseif($dedication < 170*170) $level2 = '14품관';
elseif($dedication < 180*180) $level2 = '13품관';
elseif($dedication < 190*190) $level2 = '12품관';
elseif($dedication < 200*200) $level2 = '11품관'; // 40000
elseif($dedication < 210*210) $level2 = '10품관'; // 44100
elseif($dedication < 220*220) $level2 = '9품관'; // 48400
elseif($dedication < 230*230) $level2 = '8품관'; // 52900
elseif($dedication < 240*240) $level2 = '7품관'; // 57600
elseif($dedication < 250*250) $level2 = '6품관'; // 62500
elseif($dedication < 260*260) $level2 = '5품관'; // 67600
elseif($dedication < 270*270) $level2 = '4품관'; // 72900
elseif($dedication < 280*280) $level2 = '3품관'; // 78400
elseif($dedication < 290*290) $level2 = '2품관'; // 84100
else {
$level2 = '1품관';
$dedLevel = getDedLevel($dedication);
if($dedLevel == 0){
return '품관';
}
return $level2;
//{$maxDedLevel}품관 ~ 1품관
$dedInvLevel = GameConst::$maxDedLevel - $dedLevel + 1;
return "{$dedInvLevel}품관";
}
@@ -364,16 +418,18 @@ function getExpLevel($experience) {
if($experience < 1000) {
$level = intdiv($experience, 100);
} else {
for($level = 0; $experience > (($level+1)*($level+1)*10); $level++) {
}
$level = Util::toInt(sqrt($experience/10));
}
return $level;
}
function getDedLevel($dedication) {
for($level = 0; $dedication > (($level+1)*($level+1)*100); $level++) {
}
$level = Util::valueFit(
ceil(sqrt($dedication) / 10),
0,
GameConst::$maxDedLevel
);
return $level;
}
@@ -390,9 +446,7 @@ function getLevelPer($exp, $level) {
}
function getBill(int $dedication) : int{
for($level = 0; $dedication > (($level+1)*($level+1)*100); $level++) {
}
$level = getDedLevel($dedication);
return ($level * 200 + 400);
}
@@ -400,72 +454,40 @@ function getCost(int $armtype) : int {
return GameUnitConst::byID($armtype)->cost;
}
function TechLimit($startyear, $year, $tech) : int {
$limit = 0;
if($year < $startyear+ 5 && $tech >= 1000) { $limit = 1; }
if($year < $startyear+10 && $tech >= 2000) { $limit = 1; }
if($year < $startyear+15 && $tech >= 3000) { $limit = 1; }
if($year < $startyear+20 && $tech >= 4000) { $limit = 1; }
if($year < $startyear+25 && $tech >= 5000) { $limit = 1; }
if($year < $startyear+30 && $tech >= 6000) { $limit = 1; }
if($year < $startyear+35 && $tech >= 7000) { $limit = 1; }
if($year < $startyear+40 && $tech >= 8000) { $limit = 1; }
if($year < $startyear+45 && $tech >= 9000) { $limit = 1; }
if($year < $startyear+50 && $tech >= 10000) { $limit = 1; }
if($year < $startyear+55 && $tech >= 11000) { $limit = 1; }
if($year < $startyear+60 && $tech >= 12000) { $limit = 1; }
return $limit;
function getTechLevel($tech):int{
return Util::valueFit(
floor($tech / 1000),
0,
GameConst::$maxTechLevel
);
}
function TechLimit($startyear, $year, $tech) : bool {
$relYear = $startyear - $year;
$relMaxTech = Util::valueFit(
floor($relYear / 5) + 1,
1,
GameConst::$maxTechLevel
);
$techLevel = getTechLevel($tech);
return $techLevel >= $relMaxTech;
}
function getTechAbil($tech) : int{
if($tech < 1000) { $abil = 0; }
elseif($tech < 2000) { $abil = 25; }
elseif($tech < 3000) { $abil = 50; }
elseif($tech < 4000) { $abil = 75; }
elseif($tech < 5000) { $abil = 100; }
elseif($tech < 6000) { $abil = 125; }
elseif($tech < 7000) { $abil = 150; }
elseif($tech < 8000) { $abil = 175; }
elseif($tech < 9000) { $abil = 200; }
elseif($tech < 10000) { $abil = 225; }
elseif($tech < 11000) { $abil = 250; }
elseif($tech < 12000) { $abil = 275; }
else { $abil = 300; }
return $abil;
return getTechLevel($tech) * 25;
}
function getTechCost($tech) : float{
if($tech < 1000) { $cost = 1.00; }
elseif($tech < 2000) { $cost = 1.15; }
elseif($tech < 3000) { $cost = 1.30; }
elseif($tech < 4000) { $cost = 1.45; }
elseif($tech < 5000) { $cost = 1.60; }
elseif($tech < 6000) { $cost = 1.75; }
elseif($tech < 7000) { $cost = 1.90; }
elseif($tech < 8000) { $cost = 2.05; }
elseif($tech < 9000) { $cost = 2.20; }
elseif($tech < 10000) { $cost = 2.35; }
elseif($tech < 11000) { $cost = 2.50; }
elseif($tech < 12000) { $cost = 2.65; }
else { $cost = 2.80; }
return $cost;
return 1 + getTechLevel($tech) * 0.15;
}
function getTechCall($tech) : string {
if($tech < 1000) { $str = '0등급'; }
elseif($tech < 2000) { $str = '1등급'; }
elseif($tech < 3000) { $str = '2등급'; }
elseif($tech < 4000) { $str = '3등급'; }
elseif($tech < 5000) { $str = '4등급'; }
elseif($tech < 6000) { $str = '5등급'; }
elseif($tech < 7000) { $str = '6등급'; }
elseif($tech < 8000) { $str = '7등급'; }
elseif($tech < 9000) { $str = '8등급'; }
elseif($tech < 10000) { $str = '9등급'; }
elseif($tech < 11000) { $str = '10등급'; }
elseif($tech < 12000) { $str = '11등급'; }
else { $str = '12등급'; }
return $str;
$techLevel = getTechLevel($tech);
return "{$techLevel}등급";
}
function getDexCall($dex) : string {
@@ -544,7 +566,7 @@ function getDexLog($dex1, $dex2) {
}
function getWeapName($weap) : string {
function getWeapName($weap) : ?string {
switch($weap) {
case 0: $weapname = '-'; break;
case 1: $weapname = '단도(+1)'; break;
@@ -578,7 +600,7 @@ function getWeapName($weap) : string {
return $weapname;
}
function getWeapEff($weap) : int{
function getWeapEff($weap) : ?int{
switch($weap) {
case 7: $weap = 7; break;
case 8: $weap = 7; break;
@@ -605,7 +627,7 @@ function getWeapEff($weap) : int{
return $weap;
}
function getBookName($book) : string {
function getBookName($book) : ?string {
switch($book) {
case 0: $bookname = '-'; break;
case 1: $bookname = '효경전(+1)'; break;
@@ -639,7 +661,7 @@ function getBookName($book) : string {
return $bookname;
}
function getBookEff($book) : int {
function getBookEff($book) : ?int {
switch($book) {
case 7: $book = 7; break;
case 8: $book = 7; break;
@@ -666,7 +688,7 @@ function getBookEff($book) : int {
return $book;
}
function getHorseName($horse) : string {
function getHorseName($horse) : ?string {
switch($horse) {
case 0: $horsename = '-'; break;
case 1: $horsename = '노기(+1)'; break;
@@ -700,7 +722,7 @@ function getHorseName($horse) : string {
return $horsename;
}
function getHorseEff($horse) : int {
function getHorseEff($horse) : ?int {
switch($horse) {
case 7: $horse = 7; break;
case 8: $horse = 7; break;
@@ -727,7 +749,7 @@ function getHorseEff($horse) : int {
return $horse;
}
function getItemName($item) : string {
function getItemName($item) : ?string {
switch($item) {
case 0: $itemname = '-'; break;
case 1: $itemname = '환약(치료)'; break;
@@ -757,10 +779,45 @@ function getItemName($item) : string {
case 24: $itemname = '태평청령(의술)'; break;
case 25: $itemname = '태평요술(회피)'; break;
case 26: $itemname = '둔갑천서(회피)'; break;
default: $itemname = null;
}
return $itemname;
}
function getItemInfo(?int $item):?string{
$itemInfo = [
1=>['환약(치료)', '[군사] 턴 실행 전 부상 회복. 1회용'],
2=>['수극(저격)', '[전투] 전투 개시 전 20% 확률로 저격 시도. 1회용'],
3=>['탁주(사기)', '[전투] 사기 보정 +3. 1회용'],
4=>['청주(훈련)', '[전투] 훈련 보정 +3. 1회용'],
5=>['이추(계략)', '[계략] 화계·탈취·파괴·선동 : 성공률 +10%p. 1회용'],
6=>['향낭(계략)', '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p. 1회용'],
7=>['오석산(치료)', '[군사] 턴 실행 전 부상 회복.'],
8=>['무후행군(치료)', '[군사] 턴 실행 전 부상 회복.'],
9=>['도소연명(치료)', '[군사] 턴 실행 전 부상 회복.'],
10=>['칠엽청점(치료)', '[군사] 턴 실행 전 부상 회복.'],
11=>['정력견혈(치료)', '[군사] 턴 실행 전 부상 회복.'],
12=>['과실주(훈련)', '[전투] 훈련 보정 +5'],
13=>['이강주(훈련)', '[전투] 훈련 보정 +5'],
14=>['의적주(사기)', '[전투] 사기 보정 +5'],
15=>['두강주(사기)', '[전투] 사기 보정 +5'],
16=>['보령압주(사기)', '[전투] 사기 보정 +5'],
17=>['철벽서(훈련)', '[전투] 훈련 보정 +7'],
18=>['단결도(훈련)', '[전투] 훈련 보정 +7'],
19=>['춘화첩(사기)', '[전투] 사기 보정 +7'],
20=>['초선화(사기)', '[전투] 사기 보정 +7'],
21=>['육도(계략)', '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p'],
22=>['삼략(계략)', '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p'],
23=>['청낭서(의술)', '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'],
24=>['태평청령(의술)', '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'],
25=>['태평요술(회피)', '[전투] 회피 확률 +20%p'],
26=>['둔갑천서(회피)', '[전투] 회피 확률 +20%p'],
];
return $itemInfo[$item][1]??null;
}
function getItemCost2($weap) : int {
switch($weap) {
case 0: $weapcost = 0; break;
+55 -26
View File
@@ -115,22 +115,37 @@ function getSpecial2($leader, $power, $intel, $nodex=1, $dex0=0, $dex10=0, $dex2
}
function getGenDex($general, $type) {
$type = intdiv($type, 10) * 10;
return $general["dex{$type}"];
//XXX: 지금은 동작하지만.. 병종 구성이 보궁기귀차 에서 바뀌면...
$ntype = GameUnitConst::byId($type)->armType * 10;
return $general["dex{$ntype}"]??0;
}
function addGenDex($no, $atmos, $train, $type, $exp) {
//XXX: 지금은 동작하지만.. 병종 구성이 보궁기귀차 에서 바뀌면...
$db = DB::db();
$connect=$db->get();
$type = intdiv($type, 10) * 10;
$dexType = "dex{$type}";
if($type == 30) { $exp = Util::round($exp * 0.90); } //귀병은 90%효율
elseif($type == 40) { $exp = Util::round($exp * 0.90); } //차병은 90%효율
$exp = Util::round($exp * ($atmos+$train) / 200); // 사기 + 훈련 / 200
$armType = GameUnitConst::byId($type)->armType;
if($armType == GameUnitConst::T_CASTLE){
$armType = GameUnitConst::T_SIEGE;
}
$query = "update general set {$dexType}={$dexType}+{$exp} where no='$no'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
if($armType < 0){
return;
}
$ntype = $armType*10;
$dexType = "dex{$ntype}";
if($armType == GameUnitConst::T_WIZARD) {
$exp = Util::round($exp * 0.90);
}
else if($armType == GameUnitConst::T_SIEGE) {
$exp = Util::round($exp * 0.90);
}
$exp = Util::round($exp * ($atmos + $train) / 200); // 사기 + 훈련 / 200
$db->update('general', [
$dexType=>$db->sqleval('%b + %i', $dexType, $exp)
], 'no=%i', $no);
}
@@ -395,23 +410,33 @@ function preUpdateMonthly() {
}
//첩보-1
$query = "select nation,spy from nation where spy!=''";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$nationCount = MYDB_num_rows($result);
for($i=0; $i < $nationCount; $i++) {
$nation = MYDB_fetch_array($result);
$spy = ""; $k = 0;
$cities = [];
if($nation['spy'] != "") { $cities = explode("|", (string)$nation['spy']); }
while(count($cities)) {
$cities[$k]--;
if($cities[$k]%10 != 0) { $spy .= (string)$cities[$k]; }
$k++;
if($k >= count($cities)) { break; }
if($cities[$k-1]%10 != 0) { $spy .= "|"; }
foreach($db->queryAllLists("SELECT nation, spy FROM nation WHERE spy!='' AND spy!='{}'") as [$nationNo, $rawSpy]){
if (strpos($rawSpy, '|') !== false || is_numeric($rawSpy)) {
//TODO: 0.8 버전 이후에는 삭제할 것. 이후 버전은 json으로 변경됨.
$spyInfo = [];
foreach(explode('|', $rawSpy) as $value){
$value = intval($value);
$cityNo = intdiv($value, 10);
$remainMonth = $value % 10;
$spyInfo[$cityNo] = $remainMonth;
}
}
$query = "update nation set spy='$spy' where nation='{$nation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
else{
$spyInfo = Json::decode($rawSpy);
}
foreach($spyInfo as $cityNo => $remainMonth){
if($remainMonth <= 1){
unset($spyInfo[$cityNo]);
}
else{
$spyInfo[$cityNo] -= 1;
}
}
$db->update('nation', [
'spy'=>Json::encode($spyInfo, Json::EMPTY_ARRAY_IS_DICT)
], 'nation=%i', $nationNo);
}
return true;
@@ -1381,6 +1406,10 @@ function checkEmperior() {
$serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games');
$serverName = UniqueConst::$serverName;
$db->update('ng_games', [
'winner_nation'=>$nation['nation']
], 'server_id=%s', UniqueConst::$serverID);
$db->insert('emperior', [
'phase'=>$serverName.$serverCnt.'기',
'server_id'=>UniqueConst::$serverID,
+1 -1
View File
@@ -31,7 +31,7 @@ function bar($per, $h=7) {
$per = round($per, 1);
$str = "<div class='bar_out' style='height:{$h2}px;'>
$str = "<div class='bar_out' style='height:{$h}px;'>
<div class='bar_in' style='background:url(".ServConfig::$gameImagePath."/pr{$h2}.gif)'></div>
<div style='width:{$per}%;background:url(".ServConfig::$gameImagePath."/pb{$h2}.gif)'></div>
</div>";
+27 -9
View File
@@ -60,6 +60,7 @@ function getWorldMap($req){
$session = Session::getInstance();
$userID = $session->userID;
$userGrade = $session->userGrade;
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -94,19 +95,29 @@ function getWorldMap($req){
$myNation = null;
}
$spyInfo = (object)null;
if($myNation){
$spyList = $db->queryFirstField('select `spy` from `nation` where `nation`=%i',
$rawSpy = $db->queryFirstField('select `spy` from `nation` where `nation`=%i',
$myNation);
if($spyList){
$spyList = array_map('\sammo\Util::toInt', explode("|", $spyList));
if(strpos($rawSpy, '|') !== false || is_numeric($rawSpy)){
//NOTE: 0.8 이전 데이터가 남아있으므로, 0.8버전으로 마이그레이션 이후에도 이곳은 삭제하면 안됨
$spyInfo = [];
foreach(explode('|', $rawSpy) as $value){
$value = intval($value);
$cityNo = intdiv($value, 10);
$remainMonth = $value % 10;
$spyInfo[$cityNo] = $remainMonth;
}
}
else{
$spyList = [];
else if($rawSpy != ''){
$spyInfo = Json::decode($rawSpy);
}
}
else{
$spyList = [];
if(!$spyInfo){
$spyInfo = (object)null;
}
$nationList = [];
@@ -136,13 +147,20 @@ function getWorldMap($req){
array_map('\\sammo\\Util::toInt', [$r['city'], $r['level'], $r['state'], $r['nation'], $r['region'], $r['supply']]);
}
if(($req->showMe || !$req->neutralView) && $userGrade >= 5){
$spyInfo = [];
foreach($cityList as $tmpCity){
$spyInfo[$tmpCity[0]] = 1;
}
}
return [
'startYear' => $startYear,
'year' => $year,
'month' => $month,
'cityList' => $cityList,
'nationList' => $nationList,
'spyList' => $spyList,
'spyList' => $spyInfo,
'shownByGeneralList' => $shownByGeneralList,
'myCity' => $myCity,
'myNation' => $myNation,
+75 -73
View File
@@ -84,6 +84,9 @@ function SetCrew($no, $personal, $gold, $leader, $genType, $tech, $region, $city
$db = DB::db();
$connect=$db->get();
$gameStor = KVStorage::getStorage($db, 'game_env');
[$startyear, $year] = $gameStor->getValuesAsArray(['startyear', 'year']);
$type = 0;
switch($genType) {
case 0: //무장
@@ -107,45 +110,40 @@ function SetCrew($no, $personal, $gold, $leader, $genType, $tech, $region, $city
}
}
$type = GameUnitConst::DEFAULT_CREWTYPE;
switch($sel) {
case 0:
$type = 0; //보병
if($tech >= 3000 && $city == 3) { $type = 4; } //근위병
elseif($tech >= 2000 && $city == 64) { $type = 3; } //자객병
elseif($tech >= 1000 && $region == 2) { $type = 1; } //청주병
elseif($tech >= 1000 && $region == 5) { $type = 5; } //등갑병
elseif($tech >= 1000 && $region == 7) { $type = 2; } //수병
foreach(GameUnitConst::byType(GameUnitConst::T_FOOTMAN) as $crewtype){
if($crewtype->isValid([$city], [$region], $year-$startyear, $tech)){
$type = $crewtype->id;
}
}
break;
case 1:
$type = 10; //궁병
if($tech >= 3000 && $city == 7) { $type = 14; } //석궁병
elseif($tech >= 3000 && $city == 6) { $type = 13; } //강궁병
elseif($tech >= 1000 && $region == 4) { $type = 12; } //연노병
elseif($tech >= 1000 && $region == 8) { $type = 11; } //궁기병
foreach(GameUnitConst::byType(GameUnitConst::T_ARCHER) as $crewtype){
if($crewtype->isValid([$city], [$region], $year-$startyear, $tech)){
$type = $crewtype->id;
}
}
break;
case 2:
$type = 20; //기병
if($tech >= 3000 && $city == 2) { $type = 27; } //호표기병
elseif($tech >= 2000 && $city == 63) { $type = 24; } //철기병
elseif($tech >= 2000 && $city == 67) { $type = 25; } //수렵기병
elseif($tech >= 2000 && $city == 65) { $type = 23; } //돌격기병
elseif($tech >= 2000 && $city == 66) { $type = 26; } //맹수병
elseif($tech >= 1000 && $region == 1) { $type = 21; } //백마병
elseif($tech >= 1000 && $region == 3) { $type = 22; } //중장기병
foreach(GameUnitConst::byType(GameUnitConst::T_CAVALRY) as $crewtype){
if($crewtype->isValid([$city], [$region], $year-$startyear, $tech)){
$type = $crewtype->id;
}
}
break;
}
break;
case 1: //지장
case 3: //지내정장
$type = 30; //귀병
if($tech >= 3000 && $city == 4) { $type = 34; } //악귀병
elseif($tech >= 3000 && $city == 5) { $type = 37; } //천귀병
elseif($tech >= 3000 && $city == 1) { $type = 38; } //마귀병
elseif($tech >= 2000 && $city == 69) { $type = 33; } //흑귀병
elseif($tech >= 2000 && $city == 68) { $type = 32; } //백귀병
elseif($tech >= 1000 && $region == 6) { $type = 31; } //신귀병
elseif($tech >= 3000 && $city == 3) { $type = 36; } //황귀병
elseif($tech >= 1000 && rand()%100 < 50) { $type = 35; } //남귀병
foreach(GameUnitConst::byType(GameUnitConst::T_WIZARD) as $crewtype){
if($crewtype->isValid([$city], [$region], $year-$startyear, $tech)){
$type = $crewtype->id;
}
}
break;
}
@@ -181,7 +179,7 @@ function processAI($no) {
$general = MYDB_fetch_array($result);
// 입력된 턴이 있으면 그것 실행
if($general['turn0'] != "00000000000000") {
if(DecodeCommand($general['turn0'])[0] != 0) {
return;
}
@@ -208,12 +206,9 @@ function processAI($no) {
$coreCommand = MYDB_fetch_array($result);
}
$attackable = 0;
$query = "select city from city where nation='{$general['nation']}' and supply='1' and front=1";
$result = MYDB_query($query, $connect) or Error("processAI10 ".MYDB_error($connect),"");
$cityCount = MYDB_num_rows($result);
$cityCount = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i AND supply=1 AND front=1', $general['nation']);
// 공격가능도시 있으면 1
if($cityCount > 0) { $attackable = 1; }
$attackable = $cityCount > 0;
$dipState = 0;
$query = "select no from diplomacy where me='{$general['nation']}' and state=1 and term>8";
@@ -307,10 +302,10 @@ function processAI($no) {
}
//재야인경우
if($general['npc'] == 5 && $general['level'] == 0) {
if($general['npc'] == 9 && $general['level'] == 0) {
// 오랑캐는 바로 임관
$rulerNation = $db->queryFirstField('SELECT nation FROM general WHERE `level`=12 AND npc=5 and nation not in %li ORDER BY RAND() limit 1', Json::decode($general['nations']));
$rulerNation = $db->queryFirstField('SELECT nation FROM general WHERE `level`=12 AND npc=9 and nation not in %li ORDER BY RAND() limit 1', Json::decode($general['nations']));
if($ruler) {
$command = EncodeCommand(0, 0, $rulerNation, 25); //임관
@@ -320,7 +315,7 @@ function processAI($no) {
$query = "update general set turn0='$command' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error("processAI07 ".MYDB_error($connect),"");
return;
} elseif($general['npc'] < 5 && $general['level'] == 0) {
} elseif($general['npc'] != 9 && $general['level'] == 0) {
switch(Util::choiceRandomUsingWeight([11.4, 40, 20, 28.6])) {
//임관 10%
case 0:
@@ -361,7 +356,7 @@ function processAI($no) {
}
break;
case 2: //이동 20%
$paths = explode("|", $city['path']);
$paths = explode('|', $city['path']);
$command = EncodeCommand(0, 0, $paths[rand()%count($paths)], 21);
break;
default:
@@ -377,7 +372,7 @@ function processAI($no) {
//군주가 할일
if($general['level'] == 12) {
//오랑캐인데 공격 못하면 바로 방랑/해산
if($general['npc'] == 5 && $dipState == 0 && $attackable == 0) {
if($general['npc'] == 9 && $dipState == 0 && !$attackable) {
//방랑군이냐 아니냐
if($nation['level'] == 0) {
// 해산
@@ -429,7 +424,7 @@ function processAI($no) {
return;
} elseif(rand()%4 > 0) {
//이동
$paths = explode("|", $city['path']);
$paths = explode('|', $city['path']);
$command = EncodeCommand(0, 0, $paths[rand()%count($paths)], 21);
$query = "update general set turn0='$command' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error("processAI09 ".MYDB_error($connect),"");
@@ -443,37 +438,44 @@ function processAI($no) {
}
} else {
//외교 평시에 선포
if($dipState == 0 && $attackable == 0) {
//전방 체크 먼저
do{
if($dipState != 0){
break;
}
if($attackable){
break;
}
SetNationFront($nation['nation']);
$query = "select city from city where nation='{$general['nation']}' and front=1 limit 0,1";
$result = MYDB_query($query, $connect) or Error("processAI02 ".MYDB_error($connect),"");
$frontCount = MYDB_num_rows($result);
//근접 공백지 없을때
if($frontCount == 0) {
$query = "select (sum(pop/10)+sum(agri)+sum(comm)+sum(secu)+sum(def)+sum(wall))/(sum(pop2/10)+sum(agri2)+sum(comm2)+sum(secu2)+sum(def2)+sum(wall2))*100 as dev from city where nation='{$general['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$devRate = MYDB_fetch_array($result);
//내정이 80% 이상일때
if($devRate['dev'] > 80) {
$query = "select nation from nation where level>0 order by rand()";
$result = MYDB_query($query, $connect) or Error("processAI09 ".MYDB_error($connect),"");
$nationCount = MYDB_num_rows($result);
for($i=0; $i < $nationCount; $i++) {
$youNation = MYDB_fetch_array($result);
if(isNeighbor($general['nation'], $youNation['nation'])) {
$command = EncodeCommand(0, 0, $youNation['nation'], 62);
$query = "update nation set l12turn0='$command' where nation='{$general['nation']}'";
MYDB_query($query, $connect) or Error("processAI09 ".MYDB_error($connect),"");
$rulerCommand = 1;
break;
}
}
}
$frontCount = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i AND front=1', $general['nation']);
if($frontCount > 0){
break;
}
}
$devRate = $db->queryFirstField('SELECT (sum(pop/10)+sum(agri)+sum(comm)+sum(secu)+sum(def)+sum(wall))/(sum(pop2/10)+sum(agri2)+sum(comm2)+sum(secu2)+sum(def2)+sum(wall2)) from city where nation=%i', $general['nation']);
if($devRate < 0.8){
break;
}
$nations = [];
foreach ($db->queryAllLists('SELECT nation, power FROM nation WHERE level>0') as [$youNationID, $youNationPower]) {
if(!isNeighbor($general['nation'], $youNationID)){
continue;
}
$nations[$youNationID] = 1/sqrt($youNationPower+1);
}
if(!$nations){
break;
}
$youNationID = Util::choiceRandomUsingWeight($nations);
$command = EncodeCommand(0, 0, $youNationID, 62);
$db->update('nation', [
'l12turn0'=>$command
], 'nation=%i', $general['nation']);
$rulerCommand = 1;
}while(false);
}
}
@@ -582,7 +584,7 @@ function processAI($no) {
$target = array();
// 평시거나 초반아니면서 공격가능 없으면서 병사 있으면 해제(25%)
if($dipState == 0 && $isStart == 0 && $attackable == 0 && $general['crew'] > 0 && rand()% 100 < 25) {
if($dipState == 0 && $isStart == 0 && !$attackable && $general['crew'] > 0 && rand()% 100 < 25) {
$command = EncodeCommand(0, 0, 0, 17); //소집해제
} elseif($dipState <= 1 || $isStart == 1) {
//평시이거나 선포있어도 초반이면
@@ -600,7 +602,7 @@ function processAI($no) {
//현도시가 전방이면 공격 가능성 체크
if($city['front'] > 0) {
//주변도시 체크
$paths = explode("|", $city['path']);
$paths = explode('|', $city['path']);
for($i=0; $i < count($paths); $i++) {
$query = "select city,nation from city where city='$paths[$i]'";
$result = MYDB_query($query, $connect) or Error("processAI20 ".MYDB_error($connect),"");
@@ -766,7 +768,7 @@ function processAI($no) {
$command = EncodeCommand(0, 0, 0, (rand()%2)*8 + 1); // 준비는 됐으나 아직 선포중이면 내정, 조달
} else {
//공격 & 내정
$paths = explode("|", $city['path']);
$paths = explode('|', $city['path']);
for($i=0; $i < count($paths); $i++) {
$query = "select city,nation from city where city='$paths[$i]'";
$result = MYDB_query($query, $connect) or Error("processAI21 ".MYDB_error($connect),"");
@@ -824,10 +826,10 @@ function processAI($no) {
}
switch($command) {
case "00000000000001": //내정
case EncodeCommand(0, 0, 0, 1): //내정
SetDevelop($genType, $general['no'], $general['city'], $nation['tech']);
return;
case "00000000000011": //징병
case EncodeCommand(0, 0, 0, 11): //징병
$query = "select region from city where nation='{$general['nation']}' order by rand() limit 0,1";
$result = MYDB_query($query, $connect) or Error("processAI16 ".MYDB_error($connect),"");
$selRegion = MYDB_fetch_array($result);
+178 -219
View File
@@ -814,8 +814,8 @@ function process_9(&$general) {
$log[] = "<C>●</>{$admin['month']}월:{$stype}을 <C>$score</> 조달했습니다. <1>$date</>";
}
$exp = $score * 0.7;
$ded = $score * 1.0;
$exp = $score * 0.7 / 3;
$ded = $score * 1.0 / 3;
// 성격 보정
$exp = CharExperience($exp, $general['personal']);
@@ -852,188 +852,175 @@ function process_9(&$general) {
}
function process_11(&$general, $type) {
if($type == 1){
$type = '징병';
}
else{
$type = '모병';
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
$log = [];
$alllog = [];
$history = [];
$date = substr($general['turntime'],11,5);
if($type == 1) { $defaultatmos = GameConst::$defaultAtmosLow; $defaulttrain = GameConst::$defaultTrainLow; }
else { $defaultatmos = GameConst::$defaultAtmosHigh; $defaulttrain = GameConst::$defaultTrainHigh; }
if($type === '징병') {
$defaultatmos = GameConst::$defaultAtmosLow;
$defaulttrain = GameConst::$defaultTrainLow;
}
else {
$defaultatmos = GameConst::$defaultAtmosHigh;
$defaulttrain = GameConst::$defaultTrainHigh;
}
$admin = $gameStor->getValues(['startyear', 'year', 'month']);
[$startyear, $year, $month] = $gameStor->getValuesAsArray(['startyear', 'year', 'month']);
$query = "select level,tech from nation where nation='{$general['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$nation = MYDB_fetch_array($result);
$lbonus = setLeadershipBonus($general, $nation['level']);
$query = "select * from city where city='{$general['city']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$city = MYDB_fetch_array($result);
$actLog = new ActionLogger($general['no'], $general['nation'], $year, $month);
$command = DecodeCommand($general['turn0']);
$armtype = $command[2];
$crew = $command[1];
$crewType = $command[2];
$rawCrew = $command[1];
if($armtype != $general['crewtype']) { $general['crew'] = 0; $general['train'] = $defaulttrain; $general['atmos'] = $defaultatmos; }
if($crew*100 + $general['crew'] > getGeneralLeadership($general, true, true, true)*100) {
$crew = Util::round(getGeneralLeadership($general, true, true, true) - $general['crew']/100);
if($crewType != $general['crewtype']) {
$general['crew'] = 0;
$general['train'] = $defaulttrain;
$general['atmos'] = $defaultatmos;
}
if($crew < 0) { $crew = 0; }
$cost = $crew * getCost($armtype);
//기술로 가격
$cost *= getTechCost($nation['tech']);
if($general['crew'] != 0) {
$dtype = "추가".$type;
}
else {
$dtype = $type;
}
if(!$general['nation']){
$actLog->pushGeneralActionLog("재야입니다. $dtype 실패. <1>$date</>");
return;
}
$city = $db->queryFirstRow('SELECT * FROM city WHERE city = %i', $general['city']);
if($city['nation'] != $general['nation']){
$actLog->pushGeneralActionLog("아국이 아닙니다. $dtype 실패. <1>$date</>");
return;
}
$crewTypeObj = GameUnitConst::byID($crewType);
if($crewTypeObj === null){
$actLog->pushGeneralActionLog("병종 코드 에러. $type 실패. <1>$date</>");
return;
}
[$nationLevel, $tech] = $db->queryFirstList('SELECT `level`,tech FROM nation WHERE nation=%i', $general['nation']);
$lbonus = setLeadershipBonus($general, $nationLevel);
//NOTE: 입력 변수는 100명 단위임
$crew = $rawCrew * 100;
if($crew + $general['crew'] > getGeneralLeadership($general, true, true, true)*100) {
$crew = max(0, getGeneralLeadership($general, true, true, true) * 100 - $general['crew']);
}
if($crew <= 0) {
$actLog->pushGeneralActionLog("더이상 $dtype 할 수 없습니다. $dtype 실패. <1>$date</>");
return;
}
$cost = $crewTypeObj->costWithTech($tech, $crew);
if($type === '모병') {
$cost *= 2;
}
//성격 보정
$cost = CharCost($cost, $general['personal']);
$cost = Util::round($cost);
$cost = Util::round(CharCost($cost, $general['personal']));
//특기 보정 : 보병, 궁병, 기병, 귀병, 공성, 징병
if(intdiv($armtype, 10) == 0 && $general['special2'] == 50) { $cost *= 0.9; }
if(intdiv($armtype, 10) == 1 && $general['special2'] == 51) { $cost *= 0.9; }
if(intdiv($armtype, 10) == 2 && $general['special2'] == 52) { $cost *= 0.9; }
if(intdiv($armtype, 10) == 3 && $general['special2'] == 40) { $cost *= 0.9; }
if(intdiv($armtype, 10) == 4 && $general['special2'] == 43) { $cost *= 0.9; }
//특기 보정 : 징병, 보병, 궁병, 기병, 귀병, 공성
if($general['special2'] == 72) { $cost *= 0.5; }
if($type == 1) { $dtype = "징병"; }
elseif($type == 2) { $dtype = "모병"; $cost *= 2; }
if($general['crew'] != 0) { $dtype = "추가".$dtype; }
//현재 가능한지 검사
switch($armtype) {
case 0: case 10: case 20: case 30: case 35: // 보병 궁병 기병 귀병 남귀병
$sel = 0; break;
case 1: $sel = 1; $rg = 2; break; // 청주병(중원)
case 2: $sel = 1; $rg = 7; break; // 수병(오월)
case 3: $sel = 2; $ct = 64; break; // 자객병(저)
case 4: $sel = 2; $ct = 3; break; // 근위병(낙양)
case 5: $sel = 1; $rg = 5; break; // 등갑병(남중)
case 11: $sel = 1; $rg = 8; break; // 궁기병(동이)
case 12: $sel = 1; $rg = 4; break; // 연노병(서촉)
case 13: $sel = 2; $ct = 6; break; // 강궁병(양양)
case 14: $sel = 2; $ct = 7; break; // 석궁병(건업)
case 21: $sel = 1; $rg = 1; break; // 백마병(하북)
case 22: $sel = 1; $rg = 3; break; // 중장기병(서북)
case 23: $sel = 2; $ct = 65; break; // 돌격기병(흉노)
case 24: $sel = 2; $ct = 63; break; // 철기병(강)
case 25: $sel = 2; $ct = 67; break; // 수렵기병(산월)
case 26: $sel = 2; $ct = 66; break; // 맹수병(남만)
case 27: $sel = 2; $ct = 2; break; // 호표기병(허창)
case 31: $sel = 1; $rg = 6; break; // 신귀병(초)
case 32: $sel = 2; $ct = 68; break; // 백귀병(오환)
case 33: $sel = 2; $ct = 69; break; // 흑귀병(왜)
case 34: $sel = 2; $ct = 4; break; // 악귀병(장안)
case 36: $sel = 2; $ct = 3; break; // 황귀병(낙양)
case 37: $sel = 2; $ct = 5; break; // 천귀병(성도)
case 38: $sel = 2; $ct = 1; break; // 마귀병(업)
case 40: $sel = 0; break; // 정란
case 41: $sel = 0; break; // 충차
case 42: $sel = 2; $ct = 1; break; // 벽력거(업)
case 43: $sel = 2; $ct = 5; break; // 목우(성도)
default: $sel = 0; $armtype = 0; break;
}
if($sel == 0) {
// 남귀병은 기술1등급부터
// 충차는 기술1등급부터
if($armtype == 35 && $nation['tech'] < 1000) {
$cnt = 0;
} elseif($armtype == 41 && $nation['tech'] < 1000) {
$cnt = 0;
} else {
$cnt = 1;
}
} elseif($sel == 1) {
$query = "select city,level from city where nation='{$general['nation']}' and region='$rg'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$cnt = MYDB_num_rows($result);
$rgcity = MYDB_fetch_array($result);
// 기술 1000 이상부터 지역병
if($cnt > 0 && $nation['tech'] < 1000) {
$cnt = 0;
}
} else {
$query = "select city,level from city where nation='{$general['nation']}' and city='$ct'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$cnt = MYDB_num_rows($result);
$ctcity = MYDB_fetch_array($result);
// 기술 2000 이상부터 이민족병
if($cnt > 0 && $ctcity['level'] == 4 && $nation['tech'] < 2000) {
$cnt = 0;
}
// 기술 3000 이상부터 특수병
if($cnt > 0 && $ctcity['level'] == 8 && $nation['tech'] < 3000) {
$cnt = 0;
}
}
if($cnt > 0) { $valid = 1; }
else { $valid = 0; }
// 초반 제한중 차병 불가
if($admin['year'] < $admin['startyear']+3 && intdiv($armtype, 10) == 4) {
$valid = 0;
else if($general['special2'] == 50 && $crewTypeObj->armType == GameUnitConstBase::T_FOOTMAN) { $cost *= 0.9; }
else if($general['special2'] == 51 && $crewTypeObj->armType == GameUnitConstBase::T_ARCHER) { $cost *= 0.9; }
else if($general['special2'] == 52 && $crewTypeObj->armType == GameUnitConstBase::T_CAVALRY) { $cost *= 0.9; }
else if($general['special2'] == 40 && $crewTypeObj->armType == GameUnitConstBase::T_WIZARD) { $cost *= 0.9; }
else if($general['special2'] == 53 && $crewTypeObj->armType == GameUnitConstBase::T_SIEGE) { $cost *= 0.9; }
if($general['gold'] < $cost){
$actLog->pushGeneralActionLog("자금이 모자랍니다. $dtype 실패. <1>$date</>");
return;
}
if($general['level'] == 0) {
$log[] = "<C>●</>{$admin['month']}월:재야입니다. $dtype 실패. <1>$date</>";
} elseif($city['nation'] != $general['nation']) {
$log[] = "<C>●</>{$admin['month']}월:아국이 아닙니다. $dtype 실패. <1>$date</>";
// } elseif($city['supply'] == 0) {
// $log[] = "<C>●</>{$admin['month']}월:고립된 도시입니다. $dtype 실패. <1>$date</>";
} elseif($crew <= 0) {
$log[] = "<C>●</>{$admin['month']}월:더이상 $dtype 할 수 없습니다. $dtype 실패. <1>$date</>";
} elseif($general['gold'] < $cost) {
$log[] = "<C>●</>{$admin['month']}월:자금이 모자랍니다. $dtype 실패. <1>$date</>";
} elseif($general['rice'] < $crew) {
$log[] = "<C>●</>{$admin['month']}월:군량이 모자랍니다. $dtype 실패. <1>$date</>";
} elseif($valid == 0) {
$log[] = "<C>●</>{$admin['month']}월:현재 $dtype 할 수 없는 병종입니다. $dtype 실패. <1>$date</>";
} elseif($city['pop']-30000 < $crew*100) { // 주민 30000명 이상만 가능
$log[] = "<C>●</>{$admin['month']}월:주민이 모자랍니다. $dtype 실패. <1>$date</>";
} elseif($city['rate'] < 20) {
$log[] = "<C>●</>{$admin['month']}월:민심이 낮아 주민들이 도망갑니다. $dtype 실패. <1>$date</>";
} else {
$log[] = "<C>●</>{$admin['month']}월:".GameUnitConst::byId($armtype)->name."을(를) <C>{$crew}00</>명 {$dtype}했습니다. <1>$date</>";
$exp = $crew;
$ded = $crew;
// 숙련도 증가
addGenDex($general['no'], GameConst::$maxAtmosByCommand, GameConst::$maxTrainByCommand, $armtype, $crew);
// 성격 보정
$exp = CharExperience($exp, $general['personal']);
$ded = CharDedication($ded, $general['personal']);
$atmos = Util::round(($general['atmos'] * $general['crew'] + $defaultatmos * $crew*100) / ($general['crew'] + $crew*100));
$train = Util::round(($general['train'] * $general['crew'] + $defaulttrain * $crew*100) / ($general['crew'] + $crew*100));
$general['crew'] += $crew*100;
$general['gold'] -= $cost;
// 주민수 감소 // 민심 김소
if($type == 1) { $city['rate'] = $city['rate'] - Util::round(($crew*100 / $city['pop'])*100); }
else { $city['rate'] = $city['rate'] - Util::round(($crew*100 / $city['pop'])*50); }
if($city['rate'] < 0) { $city['rate'] = 0; }
$query = "update city set pop=pop-({$crew}*100),rate='{$city['rate']}' where city='{$general['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 통솔경험, 병종 변경, 병사수 변경, 훈련치 변경, 사기치 변경, 자금 군량 하락, 공헌도, 명성 상승
$general['leader2']++;
$query = "update general set resturn='SUCCESS',leader2='{$general['leader2']}',crewtype='$armtype',crew='{$general['crew']}',train='$train',atmos='$atmos',gold='{$general['gold']}',rice=rice-'$crew',dedication=dedication+'$ded',experience=experience+'$exp' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$log = checkAbility($general, $log);
$log = uniqueItem($general, $log);
if($general['rice'] < $crew / 100) {
$actLog->pushGeneralActionLog("군량이 모자랍니다. $dtype 실패. <1>$date</>");
return;
}
pushGenLog($general, $log);
$ownCities = [];
$ownRegions = [];
foreach($db->queryFirstColumn('SELECT city FROM city WHERE nation = %i', $general['nation']) as $ownCity){
$ownCities[$ownCity] = 1;
$ownRegions[CityConst::byId($ownCity)->region] = 1;
}
$valid = $crewTypeObj->isValid($ownCities, $ownRegions, $year - $startyear, $tech);
if(!$valid) {
$actLog->pushGeneralActionLog("현재 $dtype 할 수 없는 병종입니다. $dtype 실패. <1>$date</>");
return;
}
if($city['pop']-30000 < $crew) { // 주민 30000명 이상만 가능
$actLog->pushGeneralActionLog("주민이 모자랍니다. $dtype 실패. <1>$date</>");
return;
}
if($city['rate'] < 20) {
$actLog->pushGeneralActionLog("민심이 낮아 주민들이 도망갑니다. $dtype 실패. <1>$date</>");
return;
}
$josaUl = JosaUtil::pick($crewTypeObj->name, '을');
$actLog->pushGeneralActionLog($crewTypeObj->name."{$josaUl} <C>{$crew}</>명 {$dtype}했습니다. <1>$date</>");
$exp = Util::round($crew / 100);
$ded = Util::round($crew / 100);
// 숙련도 증가
addGenDex($general['no'], GameConst::$maxAtmosByCommand, GameConst::$maxTrainByCommand, $crewType, $crew/100);
// 성격 보정
$exp = CharExperience($exp, $general['personal']);
$ded = CharDedication($ded, $general['personal']);
$atmos = Util::round(($general['atmos'] * $general['crew'] + $defaultatmos * $crew) / ($general['crew'] + $crew));
$train = Util::round(($general['train'] * $general['crew'] + $defaulttrain * $crew) / ($general['crew'] + $crew));
$general['crew'] += $crew;
$general['gold'] -= $cost;
// 주민수 감소 // 민심 감소
if($type === '징병') {
$city['rate'] -= Util::round(($crew / $city['pop'])*100);
}
else {
$city['rate'] -= Util::round(($crew / 2 / $city['pop'])*100);
}
if($city['rate'] < 0) { $city['rate'] = 0; }
$db->update('city', [
'pop'=>$db->sqleval('pop-%i', $crew),
'rate'=>$city['rate']
], 'city = %i', $general['city']);
// 통솔경험, 병종 변경, 병사수 변경, 훈련치 변경, 사기치 변경, 자금 군량 하락, 공헌도, 명성 상승
$general['leader2']++;
$db->update('general', [
'resturn'=>'SUCCESS',
'leader2'=>$general['leader2'],
'crewtype'=>$crewTypeObj->id,
'crew'=>$general['crew'],
'train'=>$train,
'atmos'=>$atmos,
'gold'=>$general['gold'],
'rice'=>$db->sqleval('rice - %i', Util::round($crew/100)),
'dedication'=>$db->sqleval('dedication + %i', $ded),
'experience'=>$db->sqleval('experience + %i', $exp)
], 'no=%i', $general['no']);
checkAbilityEx($general['no'], $actLog);
$log = uniqueItem($general, []);//TODO: uniqueItem 재 구현
$actLog->pushGeneralActionLog($log, ActionLogger::RAWTEXT);
}
function process_13(&$general) {
@@ -1060,14 +1047,10 @@ function process_13(&$general) {
$log[] = "<C>●</>{$admin['month']}월:재야입니다. 훈련 실패. <1>$date</>";
} elseif($city['nation'] != $general['nation']) {
$log[] = "<C>●</>{$admin['month']}월:아국이 아닙니다. 훈련 실패. <1>$date</>";
// } elseif($city['supply'] == 0) {
// $log[] = "<C>●</>{$admin['month']}월:고립된 도시입니다. 훈련 실패. <1>$date</>";
} elseif($general['crew'] == 0) {
$log[] = "<C>●</>{$admin['month']}월:병사가 없습니다. 훈련 실패. <1>$date</>";
} elseif($general['train'] >= GameConst::$maxTrainByCommand) {
$log[] = "<C>●</>{$admin['month']}월:병사들은 이미 정예병사들입니다. <1>$date</>";
// } elseif(intdiv($general['crewtype'], 10) == 4) {
// $log[] = "<C>●</>{$admin['month']}월:병기는 훈련이 불가능합니다. <1>$date</>";
} else {
// 훈련시
$score = Util::round(getGeneralLeadership($general, true, true, true) * 100 / $general['crew'] * GameConst::$trainDelta);
@@ -1128,16 +1111,12 @@ function process_14(&$general) {
$log[] = "<C>●</>{$admin['month']}월:재야입니다. 사기진작 실패. <1>$date</>";
} elseif($city['nation'] != $general['nation']) {
$log[] = "<C>●</>{$admin['month']}월:아국이 아닙니다. 사기진작 실패. <1>$date</>";
// } elseif($city['supply'] == 0) {
// $log[] = "<C>●</>{$admin['month']}월:고립된 도시입니다. 사기진작 실패. <1>$date</>";
} elseif($general['crew'] == 0) {
$log[] = "<C>●</>{$admin['month']}월:병사가 없습니다. 사기진작 실패. <1>$date</>";
} elseif($general['gold'] < $general['crew']/100) {
$log[] = "<C>●</>{$admin['month']}월:자금이 모자랍니다. 사기진작 실패. <1>$date</>";
} elseif($general['atmos'] >= GameConst::$maxAtmosByCommand) {
$log[] = "<C>●</>{$admin['month']}월:이미 사기는 하늘을 찌를듯 합니다. <1>$date</>";
// } elseif(intdiv($general['crewtype'], 10) == 4) {
// $log[] = "<C>●</>{$admin['month']}월:병기는 사기 진작이 불가능합니다. <1>$date</>";
} else {
$score = Util::round(getGeneralLeadership($general, true, true, true)*100 / $general['crew'] * GameConst::$atmosDelta);
$gold = $general['gold'] - Util::round($general['crew']/100);
@@ -1310,20 +1289,7 @@ function process_16(&$general) {
// 숙련도 증가
addGenDex($general['no'], GameConst::$maxAtmosByCommand, GameConst::$maxTrainByCommand, $general['crewtype'], Util::round($general['crew']/100));
// 전투 처리
$dead = processWar($general, $destcity);
// 기술력 따라서 보정
$dead['att'] = Util::round($dead['att'] * getTechCost($nation['tech']));
$dead['def'] = Util::round($dead['def'] * getTechCost($dnation['tech']));
// 사상자 누적
if($nation['nation'] > 0 && $dnation['nation'] > 0) {
$query = "update diplomacy set dead=dead+'{$dead['att']}' where me='{$nation['nation']}' and you='{$dnation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$query = "update diplomacy set dead=dead+'{$dead['def']}' where you='{$nation['nation']}' and me='{$dnation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
}
processWar($general, $destcity);
$log = uniqueItem($general, $log);
}
@@ -1743,32 +1709,32 @@ function process_31(&$general) {
$query = "update general set resturn='SUCCESS',gold='{$general['gold']}',rice='{$general['rice']}',leader2='{$general['leader2']}',dedication=dedication+'$ded',experience=experience+'$exp' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$query = "select spy from nation where nation='{$general['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$nation = MYDB_fetch_array($result);
if($nation['spy'] != "")
{
$cities = array_map('intval', explode("|", $nation['spy']));
$rawSpy = $db->queryFirstField('SELECT spy FROM nation WHERE nation = %i', $general['nation']);
if($rawSpy == ''){
$spyInfo = [];
}
else{
$cities = [];
}
$exist = 0;
for($i=0; $i < count($cities); $i++) {
if(intdiv($cities[$i], 10) == $destination) {
$exist = 1;
break;
else if(strpos($rawSpy, '|') !== false || is_numeric($rawSpy)){
//TODO: 0.8 버전 이후에는 삭제할 것. 이후 버전은 json으로 변경됨.
$spyInfo = [];
foreach(explode('|', $rawSpy) as $value){
$value = intval($value);
$cityNo = intdiv($value, 10);
$remainMonth = $value % 10;
$spyInfo[$cityNo] = $remainMonth;
}
}
// 기존 첩보 목록에 없으면 새로 등록, 있으면 갱신
if($exist == 0) {
$cities[] = $destination * 10 + 3;
} else {
$cities[$i] = $destination * 10 + 3;
else{
$spyInfo = Json::decode($rawSpy);
}
$spy = implode("|", $cities);
$query = "update nation set spy='$spy' where nation='{$general['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$spyInfo[$destination] = 3;
$db->update('nation', [
'spy'=>Json::encode($spyInfo, Json::EMPTY_ARRAY_IS_DICT)
], 'nation=%i', $general['nation']);
$log = checkAbility($general, $log);
}
@@ -1812,14 +1778,7 @@ function process_41(&$general) {
} elseif($crewexp == 0) {
$log[] = "<C>●</>{$admin['month']}월:병사가 모자랍니다. 단련 실패. <1>$date</>";
} else {
$type = intdiv($general['crewtype'], 10);
switch($type) {
case 0: $crewstr = '보병'; break;
case 1: $crewstr = '궁병'; break;
case 2: $crewstr = '기병'; break;
case 3: $crewstr = '귀병'; break;
case 4: $crewstr = '차병'; break;
}
$crewstr = GameUnitConst::allType()[GameUnitConst::byID($general['crewtype'])->armType];
if($ratio < 33) {
// 숙련도 증가
+4 -4
View File
@@ -84,7 +84,7 @@ function process_25(&$general) {
$joinedNations = Json::decode($general['nations']);
// 랜덤임관인 경우
if($general['npc'] > 2 && $where >= 98 && ($admin['scenario'] == 0 || $admin['scenario'] >= 20 || !$admin['fiction'])){
if($general['npc'] > 2 && $where >= 98 && ($admin['scenario'] < 100 || $admin['scenario'] >= 2000 || !$admin['fiction'])){
//'사실' 모드에서는 '성향'에 우선을 두되, 장수수, 랜덤에 비중을 둠
$nations = $db->query(
'SELECT nation.`name` as `name`,nation.nation as nation,scout,nation.`level` as `level`,gennum,`affinity` FROM nation join general on general.nation = nation.nation and general.level = 12 WHERE nation.nation not in %li and gennum < %i and scout = 0',
@@ -172,9 +172,9 @@ function process_25(&$general) {
$log[] = "<C>●</>{$admin['month']}월:현재 <D>{$nation['name']}</>{$josaUn} 임관이 제한되고 있습니다. 임관 실패.";
} elseif($admin['year'] < $admin['startyear']+3 && $gencount >= GameConst::$initialNationGenLimit) {
$log[] = "<C>●</>{$admin['month']}월:현재 <D>{$nation['name']}</>{$josaUn} 임관이 제한되고 있습니다. 임관 실패.";
} elseif($nation['scout'] == 1 && $general['npc'] < 5) {
} elseif($nation['scout'] == 1 && $general['npc'] != 9) {
$log[] = "<C>●</>{$admin['month']}월:현재 <D>{$nation['name']}</>{$josaUn} 임관이 금지되어 있습니다. 임관 실패.";
} elseif($general['makelimit'] > 0 && $general['npc'] < 5) {
} elseif($general['makelimit'] > 0 && $general['npc'] != 9) {
$log[] = "<C>●</>{$admin['month']}월:재야가 된지 12턴이 지나야 합니다. 임관 실패. <1>$date</>";
} elseif(in_array($nation['nation'], $joinedNations)) {
$log[] = "<C>●</>{$admin['month']}월:이미 임관했었던 국가입니다. 임관 실패. <1>$date</>";
@@ -339,7 +339,7 @@ function process_29(&$general) {
// 체섭시 무장 20%, 지장 20%, 무지장 60%
// 마이너 무장 40%, 지장 40%, 무지장 20%
$type = rand() % 10;
if($admin['scenario'] == 0) {
if($admin['scenario'] < 100) {
switch($type) {
case 0: case 1:
$leader = GameConst::$defaultStatMax - 10 + rand()%11;
+46 -3
View File
@@ -64,6 +64,42 @@ function CoreTurnTable() {
";
}
function displayCharInfo(?int $type):string{
$info = getCharInfo($type);
$text = getGenChar($type);
$templates = new \League\Plates\Engine(__dir__.'/templates');
return $templates->render('tooltip', [
'text'=>$text,
'info'=>$info,
]);
}
function displaySpecialInfo(?int $type):string{
$info = getSpecialInfo($type);
$text = getGenSpecial($type);
$templates = new \League\Plates\Engine(__dir__.'/templates');
return $templates->render('tooltip', [
'text'=>$text,
'info'=>$info,
]);
}
function displayItemInfo(?int $type):string{
$info = getItemInfo($type);
$text = getItemName($type);
$templates = new \League\Plates\Engine(__dir__.'/templates');
return $templates->render('tooltip', [
'text'=>$text,
'info'=>$info,
]);
}
function allButton() {
$db = DB::db();
@@ -167,11 +203,18 @@ function formatName(string $name, int $npc): string{
return $name;
}
function getMapHtml(){
//NOTE: 필요한가?
function getMapHtml(?string $mapTheme=null){
$templates = new \League\Plates\Engine(__dir__.'/templates');
return $templates->render('map');
if($mapTheme === null){
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$mapTheme = $gameStor->map_theme??'che';
}
return $templates->render('map', [
'mapTheme'=>$mapTheme
]);
}
function getInvitationList(array $nationList){
+2 -2
View File
@@ -298,7 +298,7 @@ function fillLowGenAll() {
}
//자동신청하고, 돈 있고, 아직 참가 안한 장수
$query = "select no,npc,name,leader,power,intel,explevel from general where tnmt='1' and tournament='0' and gold>='{$develcost}' order by rand() limit 0,64";
$query = "select no,npc,name,leader,power,intel,explevel from general where tnmt='1' and tournament='0' order by rand() limit 0,64";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$genCount = MYDB_num_rows($result);
@@ -313,7 +313,7 @@ function fillLowGenAll() {
if($genCount > 0) {
$genCount--;
$gen = MYDB_fetch_array($result);
$query = "update general set gold=gold-'{$develcost}',tournament='1' where no='{$gen['no']}'";
$query = "update general set tournament='1' where no='{$gen['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$query = "insert into tournament (no, npc, name, ldr, pwr, itl, lvl, grp, grp_no) values ('{$gen['no']}', '{$gen['npc']}', '{$gen['name']}', '{$gen['leader']}', '{$gen['power']}', '{$gen['intel']}', '{$gen['explevel']}', '$i', '$grpCount[$i]')";
+16 -12
View File
@@ -44,7 +44,7 @@ if ($me['newmsg'] == 1 || $me['newvote'] == 1) {
], 'owner=%i', $userID);
}
$admin = $gameStor->getValues(['develcost','online','conlimit','tournament','tnmt_type','turnterm','scenario','scenario_text','extended_general','fiction','npcmode','vote','vote_title']);
$admin = $gameStor->getValues(['develcost','online','conlimit','tournament','tnmt_type','turnterm','scenario','scenario_text','extended_general','fiction','npcmode','vote','vote_title','map_theme']);
$plock = $db->queryFirstField('SELECT plock FROM plock LIMIT 1');
@@ -76,7 +76,7 @@ if ($admin['npcmode'] == 0) {
$valid = 1;
}
$color = "cyan";
$mapTheme = $admin['map_theme'];
?>
<!DOCTYPE html>
<html>
@@ -87,16 +87,20 @@ $color = "cyan";
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery.redirect.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/main.js')?>
<?=WebUtil::printJS('js/base_map.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('js/map.js')?>
<?=WebUtil::printJS('js/msg.js')?>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
$(function(){
reloadWorldMap({
hrefTemplate:'b_currentCity.php?citylist={0}'
hrefTemplate:'b_currentCity.php?citylist={0}',
useCachedMap:true
});
setInterval(function(){
@@ -104,7 +108,7 @@ $(function(){
}, 10000);
});
</script>
<?=WebUtil::printCSS('css/normalize.css')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/main.css')?>
@@ -229,18 +233,18 @@ else if($session->userGrade == 4){
<table class="tb_layout bg0" style="width:1000px;">
<tr>
<td width=698 height=520 colspan=2>
<?=getMapHtml()?>
<?=getMapHtml($mapTheme)?>
</td>
<td width=298 rowspan=4><iframe seamless="seamless" name=commandlist src='commandlist.php' width=298 height=700 frameborder=0 marginwidth=0 marginheight=0 topmargin=0 scrolling=no></iframe></td>
</tr>
<form name=form2 action=preprocessing.php method=post target=commandlist>
<tr>
<td rowspan=3 width=50 valign=top><?=turnTable()?></td>
<td width=646 style="border:none;text-align:center;"><?php cityInfo(); ?></td>
<td style="width:650px;border:none;text-align:center;"><?php cityInfo(); ?></td>
</tr>
<tr>
<td width=646 align=right>
<font color=cyan><b></b> Ctrl, Shift, 드래그로 복수선택 가능     반복&amp;수정<b></b></font>
<td style='width:650px;' align=right>
<font color=cyan><b></b> Ctrl, Shift, 드래그로 복수선택 가능  반복&amp;수정<b></b></font>
<select name=sel size=1 style=color:white;background-color:black;font-size:13px;>
<option value=1>1</option>
<option value=2>2</option>
@@ -254,11 +258,11 @@ else if($session->userGrade == 4){
<option value=10>10</option>
<option value=11>11</option>
<option value=12>12</option>
</select><input type=button style=background-color:<?=GameConst::$basecolor2?>;color:white;width:50px;font-size:13px; value='반복' onclick='refreshing(this, 2,0)'><input type=button style=background-color:<?=GameConst::$basecolor2?>;color:white;width:80px;font-size:13px; value='▼미루기' onclick='refreshing(this, 2,1)'><input type=button style=background-color:<?=GameConst::$basecolor2?>;color:white;width:80px;font-size:13px; value='▲당기기' onclick='refreshing(this, 2,2)'>
</select><input type=button style='background-color:<?=GameConst::$basecolor2?>;color:white;width:70px;font-size:13px;margin-left:1ch;margin-right:2ch;' value='반복' onclick='refreshing(this, 2,0)'><input type=button style=background-color:<?=GameConst::$basecolor2?>;color:white;width:80px;font-size:13px; value='▼미루기' onclick='refreshing(this, 2,1)'><input type=button style=background-color:<?=GameConst::$basecolor2?>;color:white;width:80px;font-size:13px; value='▲당기기' onclick='refreshing(this, 2,2)'>
</td>
</tr>
<tr>
<td width=646 align=right style="border:none;">
<td align=right style="'width:650px;border:none;">
<?php commandTable(); ?>
<input id="mainBtnSubmit" type=button style=background-color:<?=GameConst::$basecolor2?>;color:white;width:110px;font-size:13px; value='실 행' onclick='refreshing(this, 3,form2)'><input type=button style=background-color:<?=GameConst::$basecolor2?>;color:white;width:110px;font-size:13px; value='갱 신' onclick='refreshing(this, 0,0)'><input type=button style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;font-size:13px; value='로비로' onclick=location.replace('../')><br>
</td>
@@ -287,7 +291,7 @@ else if($session->userGrade == 4){
<div class="message_input_form bg0">
<select id="mailbox_list" size="1">
<select name="genlist" size="1" style="color:white;background-color:black;font-size:13">
<select name="genlist" size="1" style="color:white;background-color:black;font-size:13px">
-2
View File
@@ -19,8 +19,6 @@ $username = Util::getReq('db_id');
$password = Util::getReq('db_pw');
$dbName = Util::getReq('db_name');
extractMissingPostToGlobals();
if(!$host || !$port || !$username || !$password || !$dbName){
Json::die([
'result'=>false,
+1
View File
@@ -14,6 +14,7 @@ $defaultPost = [
'showMe' => true
];
$post = Json::decode(Util::getReq('data', 'string', '{}'));
$post += $defaultPost;
if(!$session->isGameLoggedIn()){
$post['neutralView'] = true;
+1 -3
View File
@@ -8,8 +8,6 @@ $year = Util::getReq('year', 'int');
$month = Util::getReq('month', 'int');
$serverID = Util::getReq('serverID', 'string', null);
extractMissingPostToGlobals();
$url = '/a_history.php';
if(!strpos($_SERVER['HTTP_REFERER'], $url)) {
@@ -19,7 +17,7 @@ if(!strpos($_SERVER['HTTP_REFERER'], $url)) {
]);
}
if(!$year || !$month) {
if($year === null || !$month) {
Json::die([
'result'=>false,
'reason'=>'year, month가 지정되지 않았습니다'
+15 -2
View File
@@ -38,11 +38,24 @@ $connect=$db->get();
var defaultStatTotal = <?=GameConst::$defaultStatTotal?>;
var defaultStatMin = <?=GameConst::$defaultStatMin?>;
var defaultStatMax = <?=GameConst::$defaultStatMax?>;
var charInfoText = <?php
$charInfoText = [];
for($i=0;$i<=9;$i++){
//XXX:하드코딩 금지!
$charInfoText[$i] = getCharInfo($i);
}
echo Json::encode((object)$charInfoText);
?>;
</script>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/join.js')?>
</head>
@@ -106,7 +119,7 @@ if ($admin['show_img_level'] >= 1 && $member['grade'] >= 1 && $member['picture']
<tr>
<td width=498 align=right id=bg1>성격</td>
<td colspan=2>
<select name=character size=1 maxlength=15 style=color:white;background-color:black;>
<select id="selChar" name=character size=1 maxlength=15 style=color:white;background-color:black;>
<option selected value=11>????</option>
<!--
<option value=10>은둔</option>
@@ -121,7 +134,7 @@ if ($admin['show_img_level'] >= 1 && $member['grade'] >= 1 && $member['picture']
<option value=2>의협</option>
<option value=1>대의</option>
<option value=0>왕좌</option>
</select> ※보정은 도움말 참고
</select> <span id="charInfoText"></span>
</td>
</tr>
<tr>
+2 -1
View File
@@ -170,7 +170,7 @@ $special = 0;
$admin = $gameStor->getValues(['scenario', 'turnterm', 'show_img_level']);
if ($admin['scenario'] > 0) {
if ($admin['scenario'] >= 1000) {
$specage2 = $age + 3;
$specage = $age + 3;
}
@@ -222,6 +222,7 @@ $db->insert('general', [
'turntime' => $turntime,
'killturn' => 6,
'lastconnect' => $lastconnect,
'crewtype'=>GameUnitConst::DEFAULT_CREWTYPE,
'makelimit' => 0,
'age' => $age,
'startage' => $age,
-100
View File
@@ -1,100 +0,0 @@
function getCityPosition(){
return {
1: ["업", 345, 130],
2: ["허창", 330, 215],
3: ["낙양", 275, 180],
4: ["장안", 145, 165],
5: ["성도", 25, 290],
6: ["양양", 255, 290],
7: ["건업", 505, 305],
8: ["북평", 465, 65],
9: ["남피", 395, 95],
10: ["완", 270, 235],
11: ["수춘", 395, 270],
12: ["서주", 440, 250],
13: ["강릉", 245, 335],
14: ["장사", 255, 375],
15: ["시상", 360, 360],
16: ["위례", 620, 145],
17: ["계", 365, 35],
18: ["복양", 410, 170],
19: ["진류", 365, 185],
20: ["여남", 330, 260],
21: ["하비", 480, 235],
22: ["서량", 25, 50],
23: ["하내", 230, 150],
24: ["한중", 135, 205],
25: ["상용", 185, 225],
26: ["덕양", 85, 275],
27: ["강주", 70, 310],
28: ["건녕", 80, 400],
29: ["남해", 245, 480],
30: ["계양", 230, 400],
31: ["오", 510, 345],
32: ["평양", 590, 100],
33: ["사비", 605, 205],
34: ["계림", 655, 200],
35: ["진양", 295, 60],
36: ["평원", 440, 115],
37: ["북해", 470, 155],
38: ["초", 365, 230],
39: ["패", 430, 220],
40: ["천수", 70, 105],
41: ["안정", 95, 145],
42: ["홍농", 210, 175],
43: ["하변", 45, 190],
44: ["자동", 75, 245],
45: ["영안", 115, 295],
46: ["귀양", 90, 360],
47: ["주시", 30, 345],
48: ["운남", 30, 415],
49: ["남영", 135, 405],
50: ["교지", 130, 480],
51: ["신야", 250, 260],
52: ["강하", 315, 295],
53: ["무릉", 195, 355],
54: ["영릉", 190, 395],
55: ["상동", 210, 435],
56: ["여강", 380, 315],
57: ["회계", 480, 395],
58: ["고창", 350, 405],
59: ["대", 450, 480],
60: ["안평", 530, 80],
61: ["졸본", 570, 65],
62: ["이도", 680, 260],
63: ["강", 95, 35],
64: ["저", 25, 120],
65: ["흉노", 180, 95],
66: ["남만", 80, 455],
67: ["산월", 425, 430],
68: ["오환", 610, 20],
69: ["왜", 680, 320],
70: ["호관", 285, 140],
71: ["호로", 285, 205],
72: ["사곡", 240, 175],
73: ["함곡", 180, 175],
74: ["사수", 310, 185],
75: ["양평", 90, 220],
76: ["가맹", 45, 225],
77: ["역경", 410, 65],
78: ["계교", 405, 135],
79: ["동황", 515, 145],
80: ["관도", 340, 165],
81: ["정도", 400, 210],
82: ["합비", 435, 285],
83: ["광릉", 490, 275],
84: ["적도", 130, 75],
85: ["가정", 40, 160],
86: ["기산", 110, 180],
87: ["면죽", 35, 255],
88: ["이릉", 215, 295],
89: ["장판", 280, 315],
90: ["백랑", 530, 30],
91: ["적벽", 330, 325],
92: ["파양", 430, 350],
93: ["탐라", 605, 260],
94: ["유구", 625, 435],
};
}
+10 -1
View File
@@ -128,4 +128,13 @@ function getIconPath(imgsvr, picture){
else{
return pathConfig.root+'/d_pic/'+picture;
}
}
}
jQuery(function($){
$('.obj_tooltip').tooltip({
title:function(){
return $.trim($(this).find('.tooltiptext').html());
},
html:true
});
});
+1 -1
View File
@@ -564,7 +564,7 @@ $(function() {
var $name = $this.children('.i_name');
$name.addClass('nameplate');
var name = $name.find('.t_name').html();
var name = $name.find('.t_name').text();
var $work = $this.children('.i_action');
+52 -28
View File
@@ -9,19 +9,33 @@ $(function(){
var getUserType = function(,,){
var = ++;
if( < *0.2) {
if( < 40){
if(+ < ){
return "무능";
}
return "무지";
}else if( < *0.2) {
return "지";
}else if( < *0.2) {
return "무";
}else{
}
var 최대능력치 = Math.max(, , );
var 능력치2합 = Math.min(+, +, +);
if(최대능력치 >= 70 && 능력치2합 >= 최대능력치 * 1.7){
return "만능";
}
if( >= 60 && < *0.8){
return "무";
}
if( >= 60 && < *0.8){
return "지";
}
return "평범";
};
function formatScore(x) {
console.log(x);
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
@@ -53,27 +67,31 @@ $(function(){
var 장수명 = $.trim($tds.eq(1).text());
var 국가 = $.trim($tds.eq(6).text());
var 부상 = $this.data('general-wounded');
장수.html = $this.clone();
장수.장수명 = 장수명;
장수.국가 = 국가;
장수.벌점 = parseInt($tds.eq(-1).text());
장수. = parseInt($tds.eq(10).text().split('+')[0]);
장수. = parseInt($tds.eq(11).text().split('+')[0]);
장수. = parseInt($tds.eq(12).text().split('+')[0]);
장수. = parseInt($this.data('general-leadership'));
장수. = parseInt($this.data('general-power'));
장수. = parseInt($this.data('general-intel'));
장수.삭턴 = parseInt($tds.eq(-2).text());
장수.종류 = getUserType(장수., 장수., 장수.);
장수.의병 = 장수명[0]=="ⓜ" || 장수명[0]=="ⓖ";
장수.NPC = $this.data('is-npc');
if(!(국가 in 국가별)){
국가별[국가] = {};
국가별[국가].만능 = [];
국가별[국가]. = [];
국가별[국가]. = [];
국가별[국가].충차 = [];
국가별[국가].평범 = [];
국가별[국가].무지 = [];
국가별[국가]. = [];
//국가별[국가].의병 = [];
국가별[국가]. = [];
//국가별[국가].NPC = [];
}
//if(장수.의병) 국가별[국가].의병.push(장수);
//if(장수.NPC) 국가별[국가].NPC.push(장수);
국가별[국가][장수.종류].push(장수);
장수.html.hide();
@@ -93,8 +111,11 @@ $(function(){
var total = 0;
var 전투유저장수 = 0;
var 삭턴장수 = 0;
var 통솔합 = 0;
var 삭턴장수 = 0;
var 전투N장수 = 0;
var N장통솔합 = 0;
$td.html('<p class="sum" style="margin:0;font-weight:bold;color:yellow;text-align:center"></p>');
$td.css('text-indent','-5.8em').css('padding-left','5.8em');
for(var 종류명 in 국가정보){
@@ -130,15 +151,18 @@ $(function(){
$.each(테이블,function(idx,val){
var 종능 = val. + val. + val.;
if(종류명 == '무' || 종류명 == '지' || 종류명 == '충차'){
if(val.삭턴 >= 80 && !val.의병){
전투유저장수+=1;
console.log(val);
if(종류명 != '무능' && 종류명 != '무지'){
if(val.삭턴 >= 80 && !val.NPC){
전투유저장수 += 1;
if(종능 > 150) 통솔합 += val.;
else if(종능/0.75 >= 150)통솔합 += parseInt(val./0.75);
else if(종능/0.55 >= 150)통솔합 += parseInt(val./0.55);
else if(종능/0.35 >= 150)통솔합 += parseInt(val./0.35);
else if(종능/0.15 >= 150)통솔합 += parseInt(val./0.15);
통솔합 += val.;
}
if(val.삭턴 > 5 && val.NPC){
전투N장수 += 1;
N장통솔합 += val.;
}
}
@@ -146,11 +170,11 @@ $(function(){
var $obj2 = $('<span></span>');
$obj.html(val.장수명);
if(!val.의병 && val.삭턴 < 80){
if(!val.NPC && val.삭턴 < 80){
$obj.css('text-decoration','line-through');
삭턴장수+=1;
}
if(val.의병){
if(val.NPC){
$obj.css('color','cyan');
}
if(val.벌점 >= 1500) $obj.css('color','yellow');
@@ -179,7 +203,7 @@ $(function(){
$td.append($p);
}
var result = "* 총("+total+"), 전투장("+전투유저장수+", 약 "+formatScore(통솔합*100)+"명), 삭턴장("+삭턴장수+") *";
var result = "* 총("+total+"), 전투장("+전투유저장수+", 약 "+formatScore(통솔합*100)+"명), 전투N장("+전투N장수+", 약 "+formatScore(N장통솔합*100)+"명), 삭턴장("+삭턴장수+") *";
$tbl.find('.sum').html(result);
@@ -226,7 +250,7 @@ $(function(){
$btn.prop("disabled",true);
var $tr0 = $('table:eq(0) tr:eq(0)');
$tr0.append('<td><strong>*벌점 순 정렬*</strong><br><span style="color:yellow">벌점 1500점 이상</span>, <span style="color:lightgreen">벌점 200점 이상</span>, '+
'<span style="text-decoration:line-through">삭턴 장</span>, <span style="color:cyan">ⓝ장</span>'+'<br><strong>전투장 :</strong> 무장 + 지장 + 충차장 - 삭턴자(무,지,) </td>');
'<span style="text-decoration:line-through">삭턴장</span>, <span style="color:cyan">ⓝ장</span>'+'<br><strong>전투장 :</strong> 만능장 + 무장 + 지장 + 평범장 - 삭턴자(만능, 무, 지, 평범) </td>');
});
+40 -174
View File
@@ -8,94 +8,8 @@ $(function(){
var $userFrame;
window.groupList = groupList;
window.userList = userList;
var aGroup = {};
$('#troop_list tbody > tr').each(function(idx){
var $this = $(this);
//console.log(this);
//console.log($this);
if(idx%3 == 0){
aGroup = {
turn : '77:77',
turnTime : 5555,
부대장 : '에러-집합장없음',
부대명 : '에러-부대명없음',
srclist : [],
도시 : '없지롱',
list: [],
trs:[]
};
aGroup.trs.push($this);
var $children = $this.children();
var names = $.trim($children.eq(1).text()).split('【');
var 부대명 = $.trim(names[0]);
var 도시 = $.trim(names[1].substr(0,names[1].length-1));
aGroup.도시 = 도시;
aGroup.부대명 = 부대명;
aGroup.obj = $this;
aGroup.$users = $children.eq(3);
var lists = $.trim($children.eq(3).text()).split(', ');
lists.pop();
aGroup.srcList = lists;
}
else if(idx%3 == 1){
aGroup.trs.push($this);
var turnBase = $this.children().eq(0).text().split('】')[1];
//console.log(turnBase);
var userName = $this.children().eq(1).text();
var turn = turnBase;
var turnMS = turnBase.split(':');
var turnM = parseInt(turnMS[0]);
var turnS = parseInt(turnMS[1]);
var turnTime = turnM*60+turnS;
aGroup.turn = turn;
aGroup.turnTime = turnTime;
aGroup.부대장 = userName;
aGroup.obj2 = $this;
groupList[aGroup.부대명] = aGroup;
tGroup.push(aGroup);
}
else{
if($this.find('input').length==0){
$this.detach();
}
}
});
$.each(tGroup,function(idx,val){
console.log(val);
for(var i=0;i<val.trs.length;i++){
val.trs[i].detach();
}
});
tGroup.sort(function(lhs,rhs){
return lhs.turnTime-rhs.turnTime;
});
var $last = $('table:eq(1) tr:eq(-1)');
var $tbody = $('table:eq(1) tbody');
$last.detach();
console.log($last);
$.each(tGroup,function(idx,val){
for(var i=0;i<val.trs.length;i++){
$tbody.append(val.trs[i]);
}
$tbody.append('<tr><td colspan="5"></td></tr>');
});
$tbody.find('tr:eq(-1)').detach();
$tbody.append($last);
var runAnalysis = function(){
$.each(groupList,function(idx,val){
val.list = [];
@@ -111,19 +25,15 @@ $(function(){
var tmpUsers = {};
$html.each(function(idx){
if(this.tagName == "TABLE"){
cnt+=1;
if(cnt==2){
tmpUsers = $(this);
return false;
}
var $this = $(this);
if($this.attr('id') == "general_list"){
tmpUsers = $(this);
return false;
}
});
tmpUsers.find("tbody > tr").each(function(idx){
var $this = $(this);
var $부대 = $this.children('.i_troop');
var 부대 = $.trim($부대.text());
@@ -134,73 +44,27 @@ $(function(){
}
$부대.remove();
var $name = $this.children('.i_name');
$name.addClass('nameplate');
var name = $name.find('.t_name').text();
var $도시 = $this.children('.i_city');
var 도시 = $.trim($도시.text());
var $턴 = $this.children('.i_action');
//console.log($턴);
var 턴0 = $턴.text().split(':');
var = parseInt(턴0[0])*60 + parseInt(턴0[1]);
var userInfo = {
이름 : name,
부대 : 부대,
도시 : 도시,
: ,
obj : $this
};
groupList[부대].list.push(userInfo);
userList[name] = userInfo;
var generalID = parseInt($this.data('general-id'));
userList[generalID] = $this;
$this.hide();
$content.append($this);
});
$.each(groupList,function(부대명,aGroup){
aGroup.$users.html('');
$.each(aGroup.list,function(idx,userInfo){
var $user = $('<span><span class="name"></span><span class="other"></span></span>');
var $userName = $user.children('.name');
if(userInfo.이름 == aGroup.부대장){
$userName.html('*'+userInfo.이름+'*');
$userName.css('color','lightgreen');
}
else{
$userName.html(userInfo.이름);
}
if(userInfo.도시 != aGroup.도시){
$userName.css('color','red');
$user.children('.other').html('【'+userInfo.도시+'】');
}
$user.hover(function(){
var top = aGroup.obj2.offset().top + aGroup.obj2.outerHeight();
$userFrame.css('top',top);
userInfo.obj.show();
$userFrame.show();
console.log('올림!'+userInfo.이름);
},function(){
$userFrame.hide();
userInfo.obj.hide();
console.log('내림!'+userInfo.이름);
});
$user.append(', ');
aGroup.$users.append($user);
});
aGroup.$users.append('('+aGroup.list.length+'명)');
$('.troopUser').hover(function(){
var $this = $(this);
var parent = $this.closest('tr');
var generalID = parseInt($this.data('general-id'));
console.log(generalID);
var top = parent.offset().top + parent.outerHeight();
$userFrame.css('top',top);
userList[generalID].show();
$userFrame.show();
},function(){
var $this = $(this);
var parent = $this.closest('tr');
var generalID = parseInt($this.data('general-id'));
userList[generalID].hide();
$userFrame.hide();
});
}
catch(err){
@@ -223,24 +87,26 @@ $(function(){
$userFrame = $('<div id="on_mover" style="position:absolute;">'+
'<table class="tb_layout bg0" style="width:100%;"><thead><tr>'+
'<td width="98" align="center" class="bg1">이 름</td>'+
'<td width="98" align="center" class="bg1"">통무지</td>'+
'<td width="58" align="center" class="bg1">자 금</td>'+
'<td width="58" align="center" class="bg1">군 량</td>'+
'<td width="48" align="center" class="bg1">도시</td>'+
'<td width="28" align="center" class="bg1">守</td>'+
'<td width="58" align="center" class="bg1">병 종</td>'+
'<td width="68" align="center" class="bg1">병 </td>'+
'<td width="48" align="center" class="bg1">훈련</td>'+
'<td width="48" align="center" class="bg1">사기</td>'+
'<td width="148" align="center" class="bg1">명 령</td>'+
'<td width="58" align="center" class="bg1">삭턴</td>'+
'<td width="58" align="center" class="bg1">턴</td>'+
'</tr></thead><tbody class="content"></tbody></table></div>');
$userFrame = $("<div id='on_mover' style='position:absolute;'>"+
"<table class='tb_layout bg0' style='width:100%;'><thead>"+
"<tr>"+
"<td width=98 class='bg1 center'>이 름</td>"+
"<td width=98 class='bg1 center'>통무지</td>"+
"<td width=53 class='bg1 center'>자 금</td>"+
"<td width=53 class='bg1 center'>군 량</td>"+
"<td width=48 class='bg1 center'>도시</td>"+
"<td width=28 class='bg1 center'>守</td>"+
"<td width=58 class='bg1 center'>병 </td>"+
"<td width=63 class='bg1 center'>병 사</td>"+
"<td width=38 class='bg1 center'>훈련</td>"+
"<td width=38 class='bg1 center'>사기</td>"+
"<td width=213 class='bg1 center'>명 령</td>"+
"<td width=38 class='bg1 center'>삭턴</td>"+
"<td width=48 class='bg1 center'>턴</td>"+
"</tr>"+
"</thead></thead><tbody class='content'></tbody></table></div>");
$userFrame.find('thead td');
$userFrame.css('width','900px').css('margin','0').css('padding','0').css('left','50%').css('margin-left','-450px');
$userFrame.css('width','960px').css('margin','0').css('padding','0').css('left','50%').css('margin-left','-480px');
$userFrame.hide();
+14 -1
View File
@@ -150,4 +150,17 @@ jQuery(function($){
window.abilityLeadpow = abilityLeadpow;
window.abilityLeadint = abilityLeadint;
window.abilityPowint = abilityPowint;
});
var $charInfoText = $('#charInfoText');
var $selChar = $('#selChar');
$selChar.change(function(){
var $this = $(this);
var char = $this.val();
if(char in charInfoText){
$charInfoText.html(charInfoText[char]);
}
else{
$charInfoText.html('');
}
});
});
+87 -45
View File
@@ -13,6 +13,7 @@ function reloadWorldMap(option){
clickableAll:false, //어떤 경우든 클릭을 가능하게 함. 해당 동작의 동작 가능성 여부와는 별도.
selectCallback:null, //callback을 지정시 clickable과 관계 없이 해당 함수를 실행.
hrefTemplate:'#', //도시가 클릭가능할 경우 지정할 href값. {0}은 도시 id로 변환됨
useCachedMap:false, //맵 캐시를 사용
//아래부터는 post query에 들어갈 녀석
year:null, //year값, 연감등에 사용
@@ -20,11 +21,15 @@ function reloadWorldMap(option){
aux:null, //기타 넣고 싶은 값을 입력
neutralView:false, //clickable, 소속 국가, 첩보 여부 등을 반환여부를 설정
showMe:true, //반환 값에 본인이 위치한 도시 값을 반환하도록 설정. neutralView와 별개
targetJson:'j_map.php'
targetJson:'j_map.php',
//기타 보조 값
startYear:null,
};
option = $.extend(defaultOption, option);
var useCachedMap = option.useCachedMap;
var isDetailMap = option.isDetailMap;
var clickableAll = option.clickableAll;
var selectCallback = option.selectCallback;
@@ -32,6 +37,8 @@ function reloadWorldMap(option){
var cityPosition = getCityPosition();
var storedOldMapKey = 'sam.{0}.map'.format(serverNick);
var storedStartYear = 'sam.{0}.startYear'.format(serverNick);
//OBJ : startYear, year, month, cityList, nationList, spyList, shownByGeneralList, myCity
function checkReturnObject(obj){
@@ -50,6 +57,13 @@ function reloadWorldMap(option){
return obj.promise();
}
if(useCachedMap){
localStorage.setItem(storedOldMapKey, JSON.stringify([serverID, obj]));
localStorage.setItem(storedStartYear, JSON.stringify(obj.startYear));
}
$world_map.removeClass('draw_required');
return obj;
}
@@ -119,59 +133,16 @@ function reloadWorldMap(option){
};
}
function convertSpyList(arr){
var result = [];
arr.forEach(function(v){
var cityId = (v / 10) | 0;
var spy = v % 10;
result[cityId] = spy;
});
return result;
}
var cityList = obj.cityList.map(toCityObj);
var nationList = obj.nationList.map(toNationObj);
nationList = convertDictById(nationList); //array of object -> dict
var spyList = convertSpyList(obj.spyList);//Array -> Dict
var spyList = obj.spyList;
var shownByGeneralList = convertSet(obj.shownByGeneralList);//Array -> Set
var myCity = obj.myCity;
var myNation = obj.myNation;
function formatCityInfo(city) {
var region_str = '';
var level_str = '';
switch(city.region) {
case 1: region_str = "【하북|"; break;
case 2: region_str = "【중원|"; break;
case 3: region_str = "【서북|"; break;
case 4: region_str = "【서촉|"; break;
case 5: region_str = "【남중|"; break;
case 6: region_str = "【 초|"; break;
case 7: region_str = "【오월|"; break;
case 8: region_str = "【동이|"; break;
}
switch(city.level) {
case 1: level_str = "수】"; break;
case 2: level_str = "진】"; break;
case 3: level_str = "관】"; break;
case 4: level_str = "이】"; break;
case 5: level_str = "소】"; break;
case 6: level_str = "중】"; break;
case 7: level_str = "대】"; break;
case 8: level_str = "특】"; break;
}
city.text = region_str + level_str + city.name;
city.region_str = region_str;
city.level_str = level_str;
return city;
}
function mergePositionInfo(city){
var id = city.id;
@@ -288,6 +259,9 @@ function reloadWorldMap(option){
}
$imgObj.append($flagObj);
}
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
$imgObj.append($nameObj);
$map_body.append($cityObj);
@@ -348,6 +322,8 @@ function reloadWorldMap(option){
$imgObj.append($capitalObj);
}
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
$imgObj.append($nameObj);
$map_body.append($cityObj);
});
@@ -427,6 +403,25 @@ function reloadWorldMap(option){
return obj;
}
var $hideCityNameBtn = $world_map.find('.map_toggle_cityname');
if(localStorage.getItem('sam.hideMapCityName') == 'yes'){
$world_map.addClass('hide_cityname');
$hideCityNameBtn.addClass('active').attr('aria-pressed', 'true');
}
$hideCityNameBtn.click(function(){
//이전 상태 확인
var state = !$hideCityNameBtn.hasClass('active');
if(state){
$world_map.addClass('hide_cityname');
localStorage.setItem('sam.hideMapCityName', 'yes');
}
else{
$world_map.removeClass('hide_cityname');
localStorage.setItem('sam.hideMapCityName', 'no');
}
});
if(isDetailMap){
$world_map.addClass('map_detail');
}
@@ -458,5 +453,52 @@ function reloadWorldMap(option){
.then(setMouseWork)
.then(setCityClickable)
.then(saveCityInfo);
if($world_map.hasClass('draw_required')){
if(useCachedMap){
//일단 불러옴
do{
var storedMap = localStorage.getItem(storedOldMapKey);
if(!storedMap){
break;
}
storedMap = JSON.parse(storedMap);
var storedServerID = storedMap[0];
if(storedServerID != serverID){
break;
}
storedMap = storedMap[1];
storedMap = setMapBackground(storedMap);
storedMap = convertCityObjs(storedMap);
if(isDetailMap){
storedMap = drawDetailWorldMap(storedMap);
}
else{
storedMap = drawBasicWorldMap(storedMap);
}
storedMap = setMouseWork(storedMap);
storedMap = setCityClickable(storedMap);
storedMap = saveCityInfo(storedMap);
}while(false);
}
else if(option.year && option.month){
var startYear = localStorage.getItem(storedStartYear);
if(startYear){
startYear = JSON.parse(startYear);
}
else{
startYear = option.year;
}
var tmp = {
year : option.year,
month : option.month,
startYear : startYear
};
setMapBackground(tmp);
}
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+12 -6
View File
@@ -128,7 +128,7 @@ function redrawMsg(deferred){
var $msgs = msgSource.map(function(msg){
var contactTarget = (msg.src.id != myGeneralID) ? msg.src.id : msg.dest.id;
if(needRefreshLastContact && contactTarget != myGeneralID)
if(needRefreshLastContact && contactTarget != myGeneralID && contactTarget in generalList)
{
needRefreshLastContact = false;
$('#last_contact').val(contactTarget).html(generalList[contactTarget].textName).show();
@@ -150,6 +150,12 @@ function redrawMsg(deferred){
msg.defaultIcon = pathConfig.sharedIcon+'/default.jpg';
if(msgType == 'diplomacy'){
msg.allowButton = myGeneralLevel>4;
}
else{
msg.allowButton = true;
}
var msgHtml = TemplateEngine(messageTemplate, msg);
@@ -331,18 +337,18 @@ function refreshMailboxList(obj){
function registerGlobal(basicInfo){
myNation = {
window.myNation = {
'id':basicInfo.myNationID,
'mailbox':basicInfo.myNationID+9000,
'color':'#000000',
'nation':'재야'
};
lastMsg = {
window.lastMsg = {
id : basicInfo.lastContact
};
myGeneralID = basicInfo.generalID;
isChief = basicInfo.isChief;
myGeneralLevel = basicInfo.generalLevel;
window.myGeneralID = basicInfo.generalID;
window.isChief = basicInfo.isChief;
window.myGeneralLevel = basicInfo.generalLevel;
}
function activateMessageForm(){
+35 -1
View File
@@ -3,11 +3,19 @@ var templateGeneralCard =
<h4 class="bg1 with_border"><%name%></h4>\
<h4><img src="<%iconPath%>" height=64 width=64></h4>\
<p><%leader%> / <%power%> / <%intel%><br>\
<%special%> / <%special2%></p>\
<%specialText%> / <%special2Text%></p>\
<button type="subject" class="with_skin with_border select_btn" value="<%no%>" name="pick">빙의하기</button>\
<label><input <%keepCnt?"":disabled="disabled"%> type="checkbox" value="<%no%>" name="keep[]" class="keep_select">보관(<%keepCnt%>)</label>\
</div>';
var templateSpecial =
'<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"><%text%>\
<span class="tooltiptext">\
<%info%>\
</span>\
</span>\
';
function pickGeneral(){
$btn = $(this);
@@ -85,12 +93,38 @@ function printGenerals(value){
$.each(pick, function(idx, cardData){
cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture);
if(cardData.special in specialInfo){
cardData.specialText = TemplateEngine(templateSpecial, {
text:cardData.special,
info:specialInfo[cardData.special]
});
}
else{
cardData.specialText = cardData.special;
}
if(cardData.special2 in specialInfo){
cardData.special2Text = TemplateEngine(templateSpecial, {
text:cardData.special2,
info:specialInfo[cardData.special2]
});
}
else{
cardData.special2Text = cardData.special2;
}
var $card = $(TemplateEngine(templateGeneralCard, cardData));
console.log($card);
$('.card_holder').append($card);
$card.find('.select_btn').click(pickGeneral);
$card.find('.obj_tooltip').tooltip({
title:function(){
return $.trim($(this).find('.tooltiptext').html());
},
html:true
});
});
updatePickMoreTimer();
+2 -2
View File
@@ -1,5 +1,5 @@
<div
class="msg_plate msg_plate_<%msgType%> msg_plate_<%nationType%>""
class="msg_plate msg_plate_<%msgType%> msg_plate_<%nationType%>"
id="msg_<%id%>"
data-id="<%id%>"
>
@@ -42,5 +42,5 @@
<div class="msg_content"><%e(text)%></div>
<%if(this.option && this.option.action) {%>
<div class="msg_prompt">
<button class="prompt_yes btn_prompt">수락</button> <button class="prompt_no btn_prompt">거절</button>
<button class="prompt_yes btn_prompt" <%allowButton?'':'disabled="disabled"'%>>>수락</button> <button class="prompt_no btn_prompt" <%allowButton?'':'disabled="disabled"'%>>거절</button>
</div><%} %></div></div>
+1 -1
View File
@@ -54,7 +54,7 @@ function MessageBox($str)
function LogText($prefix, $variable)
{
$text = sprintf('%s : %s'."\n", $prefix, var_export($variable, true));
$text = sprintf('%s : %s'."\r\n", $prefix, var_export($variable, true));
file_put_contents(ROOT.'/d_log/dbg_logs.txt', $text, FILE_APPEND);
}
+3 -5
View File
@@ -14,11 +14,9 @@ $turn = Util::getReq('turn', 'array_int');
$sel = Util::getReq('sel', 'int');
$commandtype = Util::getReq('commandtype', 'int');
extractMissingPostToGlobals();
increaseRefresh("턴입력", 1);
if(!$turn || $commandtype === null){
if(!$turn || $commandtype === null || $sel === null){
header('location:commandlist.php');
die();
}
@@ -57,8 +55,8 @@ switch($commandtype) {
case 8: command_Single($turn, 8); break; //치안 강화
case 9: command_Single($turn, 9); break; //자금 조달
// case 11: command_11( $turn, 11); break; //징병
// case 12: command_12( $turn, 12); break; //모병
// case 11: command_11( $turn, 11, false); break; //징병
// case 12: command_11( $turn, 12, true); break; //모병
case 13: command_Single($turn, 13); break; //훈련
case 14: command_Single($turn, 14); break; //사기진작
case 15: command_Single($turn, 0); break; //전투태세
+1877
View File
@@ -0,0 +1,1877 @@
<?php
namespace sammo;
function processWar($general, $city) {
'@phan-var array<string,int|string|null> $general';
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
$templates = new \League\Plates\Engine(__dir__.'/templates');
$date = substr($general['turntime'],11,5);
$admin = $gameStor->getAll();
$year = $admin['year'];
$month = $admin['month'];
$log = [];
$batlog = [];
$batres = [];
$opplog = [];
$oppbatlog = [];
$oppbatres = [];
$alllog = [];
$history = [];
$deadAmount = [
'att'=>0,
'def'=>0
];
$generalCrewType = GameUnitConst::byID($general['crewtype']);
$warphase = $generalCrewType->speed; //병종간 페이즈 수 얻기
// 특기보정 : 돌격
if($general['special2'] == 60) { $warphase += 1; }
$genAtmos = 0;
if($general['item'] == 3) {
//탁주 사용
$genAtmos += 3;
$query = "update general set item=0 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$josaUl = JosaUtil::pick(getItemName($general['item']), '을');
$log[] = "<C>●</><C>".getItemName($general['item'])."</>{$josaUl} 사용!";
$general['item'] = 0;
} elseif($general['item'] >= 14 && $general['item'] <= 16) {
//의적주, 두강주, 보령압주 사용
$genAtmos += 5;
} elseif($general['item'] >= 19 && $general['item'] <= 20) {
//춘화첩, 초선화 사용
$genAtmos += 7;
}
$genTrain = 0;
if($general['item'] == 4) {
//청주 사용
$genTrain += 3;
$query = "update general set item=0 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$josaUl = JosaUtil::pick($general['item'], '을');
$log[] = "<C>●</><C>".getItemName($general['item'])."</>{$josaUl} 사용!";
$general['item'] = 0;
} elseif($general['item'] >= 12 && $general['item'] <= 13) {
//과실주, 이강주 사용
$genTrain += 5;
} elseif($general['item'] >= 17 && $general['item'] <= 18) {
//철벽서, 단결도 사용
$genTrain += 7;
}
// 우선 스케일링
$city['def'] *= 10;
$city['wall'] *= 10;
$query = "select level from city where city='{$general['city']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$originCity = MYDB_fetch_array($result);
$query = "select nation,level,name,capital,tech,type from nation where nation='{$general['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$nation = MYDB_fetch_array($result);
setLeadershipBonus($general, $nation['level']);
$query = "select nation,level,name,rice,capital,tech,type from nation where nation='{$city['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$destnation = MYDB_fetch_array($result) ?: [
'nation'=>0,
'capital'=>0,
'level'=>0,
'rice'=>2000,
'type'=>0,
'tech'=>0
];
//장수수 구함
$query = "select no from general where nation='{$general['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$gencount = MYDB_num_rows($result);
if($gencount < GameConst::$initialNationGenLimit) $gencount = GameConst::$initialNationGenLimit;
//장수수 구함
$query = "select no from general where nation='{$destnation['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$destgencount = MYDB_num_rows($result);
if($destgencount < GameConst::$initialNationGenLimit) $destgencount = GameConst::$initialNationGenLimit;
$genAtmosBonus = 0; $genTrainBonus = 0;
$oppAtmosBonus = 0; $oppTrainBonus = 0;
//공격자 수도보정
if($nation['capital'] == $general['city']) { $genAtmosBonus += 5; }
//방어자 수도보정
//if($destnation['capital'] == $city['city']) { $oppTrainBonus += 5; }
//관,진,수진 보정
if($city['level'] == 1) { $oppTrainBonus += 5; } // 방어도시가 수진이면 방어자 방어보정
if($originCity['level'] == 2) { $genAtmosBonus += 5; } // 출병도시가 진이면 공격자 공격보정
if($city['level'] == 3) { $oppTrainBonus += 5; } // 방어도시가 관이면 방어자 방어보정
$josaRo = JosaUtil::pick($city['name'], '로');
$josaYi = JosaUtil::pick($general['name'], '이');
$alllog[] = "<C>●</>{$month}월:<D><b>{$nation['name']}</b></>의 <Y>{$general['name']}</>{$josaYi} <G><b>{$city['name']}</b></>{$josaRo} 진격합니다.";
$log[] = "<C>●</>{$month}월:<G><b>{$city['name']}</b></>{$josaRo} <M>진격</>합니다. <1>$date</>";
// 목표 도시내에 목표 국가 소속 장수 중, 병사가 있는 능력치합+병사수 순으로 훈,사 60, 80 이상
$query = "select no,name,turntime,personal,special2,crew,crewtype,atmos,train,intel,intel2,book,power,power2,weap,injury,leader,leader2,horse,item,explevel,level,rice,leader+power+intel+weap+horse+book+crew/100 as sum,dex0,dex10,dex20,dex30,dex40 from general where city='{$city['city']}' and nation='{$city['nation']}' and nation!=0 and crew>'0' and rice>round(crew/100) and ((train>=60 and atmos>=60 and mode=1) or (train>=80 and atmos>=80 and mode=2)) order by sum desc";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$opposecount = MYDB_num_rows($result);
$exp = 0; //병사 소진 시킨 만큼
$opexp = 0;
$exp2 = 1; //능력경험치
$phase = 0;
while($phase < $warphase) {
// 장수가 없어서 도시 공격하려했으나 병량없을시
if($opposecount == 0 && $destnation['nation'] > 0 && $destnation['rice'] <= 0 && $city['supply'] == 1) {
$general['train'] += 1; //훈련 상승
if($general['train'] > GameConst::$maxTrainByWar) { $general['train'] = GameConst::$maxTrainByWar; }
$query = "update general set recwar='{$general['turntime']}',train='{$general['train']}',warnum=warnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$alllog[] = "<C>●</>{$month}월:병량 부족으로 <G><b>{$city['name']}</b></>의 수비병들이 <R>패퇴</>합니다.";
$josaUl = JosaUtil::pick($city['name'], '을');
$josaYi = JosaUtil::pick($general['name'], '이');
$history[] = "<C>●</>{$year}{$month}월:<M><b>【패퇴】</b></><D><b>{$destnation['name']}</b></>{$josaYi} 병량 부족으로 <G><b>{$city['name']}</b></>{$josaUl} 뺏기고 말았습니다.";
pushGenLog($general, $log);
pushGeneralPublicRecord($alllog, $year, $month);
pushWorldHistory($history);
$log = [];
$alllog = [];
$history= [];
//패퇴시 병량보충
$destnation['rice'] += 500;
$query = "update nation set rice='{$destnation['rice']}' where nation='{$destnation['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//내정 피폐
$query = "update city set agri=agri*0.5,comm=comm*0.5,secu=secu*0.5 where city='{$city['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$city = addConflict($city, $general['nation'], 1);//NOTE: 이 경우 두 국가가 분쟁 중인 경우에는 병량패퇴의 이득이 없다.
ConquerCity($admin, $general, $city, $nation, $destnation);
break;
// 장수가 없어서 도시 공격
} elseif($opposecount == 0) {
$opposeCrewType = GameUnitConst::byId(GameUnitConst::T_CASTLE);
$josaRo = JosaUtil::pick($generalCrewType->name, '로');
$josaYi = JosaUtil::pick($general['name'], '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>{$josaYi} {$generalCrewType->name}{$josaRo} 성벽을 공격합니다.";
$log[] = "<C>●</>{$generalCrewType->name}{$josaRo} 성벽을 <M>공격</>합니다.";
$general['train'] += 1; //훈련 상승
if($general['train'] > GameConst::$maxTrainByWar) { $general['train'] = GameConst::$maxTrainByWar; }
$query = "update general set recwar='{$general['turntime']}',train='{$general['train']}',warnum=warnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$mykillnum = 0; $mydeathnum = 0;
while($phase < $warphase) {
$phase++;
$myAtt = $generalCrewType->getComputedAttack($general, $nation['tech']);
$myDef = $generalCrewType->getComputedDefence($general, $nation['tech']);
$cityAtt = $opposeCrewType->getComputedAttack($city, $destnation['tech']);
$cityDef = $opposeCrewType->getComputedDefence($city, $destnation['tech']);
// 감소할 병사 수
$cityCrew = GameConst::$armperphase + $myAtt - $cityDef;
$myCrew = GameConst::$armperphase + $cityAtt - $myDef;
if($cityCrew <= 0) { $cityCrew = rand() % 90 + 10; }
if($myCrew <= 0) { $myCrew = rand() % 90 + 10; }
//훈련 사기따라
$myCrew = getCrew($myCrew, $admin['city_rate']+$oppAtmosBonus, CharTrain($general['train']+$genTrain+$genTrainBonus, $general['personal']));
$cityCrew = getCrew($cityCrew, CharAtmos($general['atmos']+$genAtmos+$genAtmosBonus, $general['personal']), $admin['city_rate']+$oppTrainBonus);
//숙련도 따라
$genDexAtt = getGenDex($general, $general['crewtype']);
$genDexDef = getGenDex($general, GameUnitConst::T_CASTLE);
$cityCrew *= getDexLog($genDexAtt, ($admin['city_rate']-60)*7200);
$myCrew *= getDexLog(($admin['city_rate']-60)*7200, $genDexDef);
$cityCrew *= $generalCrewType->getAttackCoef($opposeCrewType);
$myCrew *= $generalCrewType->getDefenceCoef($opposeCrewType);
$avoid = 1;
// 병종간 특성
if($generalCrewType->magicCoef) {
$int = Util::round(getGeneralIntel($general, true, true, true, false));
$ratio2 = $int / 100 * $generalCrewType->magicCoef;
// 특기보정 : 신산
if($general['special2'] == 41) { $ratio2 += 0.2; }
if(Util::randBool($ratio2)) {
$ratio = rand() % 100; // 0~99
// 특기보정 : 귀병, 신산, 환술, 신중
if($general['special2'] == 40) { $ratio += 20; }
if($general['special2'] == 41) { $ratio += 20; }
if($general['special2'] == 42) { $ratio += 10; }
if($general['special2'] == 44) { $ratio += 100; }
if($ratio >= 30) {
// 특기보정 : 환술, 집중
if($general['special2'] == 42) { $cityCrew *= 1.3; }
if($general['special2'] == 43) { $cityCrew *= 1.5; }
$type = rand() % 3;
switch($type) {
case 0:
$batlog[] = "<C>●</><D>급습</>을 <C>성공</>했다!";
$cityCrew *= 1.2;
break;
case 1:
$batlog[] = "<C>●</><D>위보</>를 <C>성공</>했다!";
$cityCrew *= 1.4;
break;
case 2:
$batlog[] = "<C>●</><D>혼란</>을 <C>성공</>했다!";
$cityCrew *= 1.6;
break;
}
} else {
$type = rand() % 3;
switch($type) {
case 0:
$batlog[] = "<C>●</><D>급습</>을 <R>실패</>했다!";
$cityCrew /= 1.2; $myCrew *= 1.2;
break;
case 1:
$batlog[] = "<C>●</><D>위보</>를 <R>실패</>했다!";
$cityCrew /= 1.4; $myCrew *= 1.4;
break;
case 2:
$batlog[] = "<C>●</><D>혼란</>을 <R>실패</>했다!";
$cityCrew /= 1.6; $myCrew *= 1.6;
break;
}
}
}
}
//군주 공격 보정 10%
if($general['level'] == 12) {
$cityCrew = $cityCrew * 1.10;
//참모, 장군 공격 보정 5%
} elseif($general['level'] == 11 || $general['level'] == 10 || $general['level'] == 8 || $general['level'] == 6) {
$cityCrew = $cityCrew * 1.05;
}
//레벨 보정
$cityCrew = $cityCrew * (100 + $general['explevel']/6)/100;
// 특기보정 : 공성, 기병, 돌격, 무쌍, 보병, 견고, 의술(청낭서,태평청령)
if($general['special2'] == 53) { $cityCrew *= 2.00; }
if($general['special2'] == 52) { $cityCrew *= 1.20; }
if($general['special2'] == 60) { $cityCrew *= 1.10; }
if($general['special2'] == 61) { $cityCrew *= 1.10; }
if($general['special2'] == 50) { $myCrew *= 0.90; }
if($general['special2'] == 62) { $myCrew *= 0.90; }
$ratio = rand() % 100; // 0 ~ 99
if(($general['special2'] == 73 || $general['item'] == 23 || $general['item'] == 24) && $ratio > 80 && $avoid == 1) {
$batlog[] = "<C>●</><C>치료</>했다!</>";
$myCrew /= 1.5; // 66%만 소모
$avoid = 0;
}
//크리
$rd = rand() % 100; // 0 ~ 99
$ratio = $generalCrewType->getCriticalRatio($general);
// 특기보정 : 무쌍, 필살
if($general['special2'] == 61) { $ratio += 10; }
if($general['special2'] == 71) { $ratio += 20; }
if($ratio >= $rd && $avoid == 1) {
$batlog[] = "<C>●</><C>필살</>공격!</>";
$cityCrew = CriticalScore2($cityCrew);
$avoid = 0;
}
//회피
$ratio = rand() % 100; // 0 ~ 99
$ratio2 = $generalCrewType->avoid; //회피율
$ratio2 = Util::round($ratio2 * $general['train'] / 100); //훈련 반영
//특기보정 : 궁병
if($general['special2'] == 51) { $ratio2 += 20; }
//도구 보정 : 둔갑천서, 태평요술
if($general['item'] == 26 || $general['item'] == 25) { $ratio2 += 20; }
LogText('avoid0', [date("Ymd_His"), $generalCrewType->id, $general['train'], $ratio2]);
if($ratio < $ratio2 && $avoid == 1) {
LogText('avoid0', true);
$batlog[] = "<C>●</><C>회피</>했다!</>";
$myCrew /= 5; // 20%만 소모
$avoid = 0;
}
//랜타추가
$cityCrew *= (rand() % 21 + 90)/100; // 90~110%
$myCrew *= (rand() % 21 + 90)/100; // 90~110%
//특기보정 : 위압
if($general['special2'] == 63 && $phase == 1 && $general['crew'] >= 1000 && $general['atmos'] >= 90 && $general['train'] >= 90) {
$batlog[] = "<C>●</>상대에게 <C>위압</>을 줬다!</>";
$myCrew = 0;
}
$general['crew'] -= Util::round($myCrew);
$city['def'] -= Util::round($cityCrew);
$city['wall'] -= Util::round($cityCrew);
$tempMyCrew = $myCrew; $tempCityCrew = $cityCrew;
$tempGeneralCrew = $general['crew']; $tempCityDef = $city['def'];
if($city['wall'] <= 0) { $city['wall'] = 0; }
if($general['crew'] <= 0 && $city['def'] <= 0) {
$r1 = $tempGeneralCrew / $tempMyCrew;
$r2 = $tempCityDef / $tempCityCrew;
if($r1 > $r2) {
$offset = Util::round($tempCityDef*$tempMyCrew/$tempCityCrew);
$myCrew += $offset;
$general['crew'] -= $offset;
$cityCrew += $tempCityDef;
$city['def'] = 0;
} else {
$offset = Util::round($tempGeneralCrew*$tempCityCrew/$tempMyCrew);
$cityCrew += $offset;
$city['def'] -= $offset;
$myCrew += $tempGeneralCrew;
$general['crew'] = 0;
}
} elseif($general['crew'] * $city['def'] <= 0) {
if($city['def'] < 0) {
$offset = Util::round($tempCityDef*$tempMyCrew/$tempCityCrew);
$myCrew += $offset;
$general['crew'] -= $offset;
$cityCrew += $tempCityDef;
$city['def'] = 0;
}
if($general['crew'] < 0) {
$offset = Util::round($tempGeneralCrew*$tempCityCrew/$tempMyCrew);
$cityCrew += $offset;
$city['def'] -= $offset;
$myCrew += $tempGeneralCrew;
$general['crew'] = 0;
}
}
$exp += $cityCrew;
$opexp += $myCrew;
$general['crew'] = Util::round($general['crew']);
$cityCrew = Util::round($cityCrew);
$myCrew = Util::round($myCrew);
$batlog[] = "<C>●</> $phase : <Y1>【{$general['name']}】</> <C>{$general['crew']} (-$myCrew)</> VS <C>{$city['def']} (-$cityCrew)</> <Y1>【{$city['name']}】</>";
$mykillnum += $cityCrew; $mydeathnum += $myCrew;
// 중간 쌀 체크
$myRice = Util::round($exp / 50);
// 성격 보정
$myRice = CharExperience($myRice, $general['personal']);
// 쌀 소모
$myRice = ($myRice * 5 * getCrewtypeRice($generalCrewType, $nation['tech']));
// 결과 쌀
$myRice = $general['rice'] - $myRice;
if($myRice <= Util::round($general['crew']/100)) { break; }
if($city['def'] <= 0) { break; }
if($general['crew'] <= 0) { break; }
}
$render_attacker = [
'crewtype' => mb_substr($generalCrewType->name, 0, 2),
'name'=> $general['name'],
'remain_crew' => $general['crew'],
'killed_crew' => -$mydeathnum
];
$render_defender = [
'crewtype' => '성벽',
'name'=> $city['name'],
'remain_crew' => $city['def'],
'killed_crew' => -$mykillnum
];
$res = str_replace(["\r\n", "\r", "\n"], '', $templates->render('small_war_log',[
'year'=>$year,
'month'=>$month,
'war_type'=>'siege',
'war_type_str'=>'→',
'me' => $render_attacker,
'you' => $render_defender,
]));
$log[] = $res;//TODO: $log를 출력할 때 date에 대해선 숨겨야 함.
$batlog[] = $res;
$batres[] = $res;
$deadAmount['att'] = $deadAmount['att'] + $mydeathnum;
$deadAmount['def'] = $deadAmount['def'] + $mykillnum;
// 도시쌀 소모 계산
$opexp = Util::round($opexp / 50 * 0.8);
$rice = Util::round($opexp * 5 * getCrewtypeRice($opposeCrewType, 0) * ($admin['city_rate']/100 - 0.2));
$destnation['rice'] -= $rice;
if($destnation['rice'] < 0) { $destnation['rice'] = 0; }
$query = "update nation set rice='{$destnation['rice']}' where nation='{$destnation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
pushAdminLog(["성벽 쌀 소모 : $rice"]);
//원래대로 스케일링
$city['def'] = Util::round($city['def'] / 10);
$city['wall'] = Util::round($city['wall'] / 10);
//내정 감소
$dec = Util::round($cityCrew / 10);
$city['agri'] -= $dec;
$city['comm'] -= $dec;
$city['secu'] -= $dec;
if($city['agri'] < 0) { $city['agri'] = 0; }
if($city['comm'] < 0) { $city['comm'] = 0; }
if($city['secu'] < 0) { $city['secu'] = 0; }
// 병사수 변경
$query = "update general set crew='{$general['crew']}',killcrew=killcrew+'$mykillnum',deathcrew=deathcrew+'$mydeathnum' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 숙련도 증가
addGenDex($general['no'], $general['atmos'], $general['train'], $general['crewtype'], $mykillnum);
addGenDex($general['no'], $general['atmos'], $general['train'], GameUnitConstBase::T_CASTLE, $mydeathnum);
// 죽은수 기술로 누적
$num = Util::round($mydeathnum * 0.01);
// 국가보정
if($nation['type'] == 3 || $nation['type'] == 13) { $num *= 1.1; }
if($nation['type'] == 5 || $nation['type'] == 6 || $nation['type'] == 7 || $nation['type'] == 8 || $nation['type'] == 12) { $num *= 0.9; }
// 부드러운 기술 제한
if(TechLimit($admin['startyear'], $year, $nation['tech'])) { $num = intdiv($num, 4); }
$query = "update nation set totaltech=totaltech+'$num',tech=totaltech/'$gencount' where nation='{$nation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 죽은수 기술로 누적
$num = Util::round($mykillnum * 0.01);
// 국가보정
if($destnation['type'] == 3 || $destnation['type'] == 13){
$num *= 1.1;
}
if($destnation['type'] == 5 || $destnation['type'] == 6 || $destnation['type'] == 7 || $destnation['type'] == 8 || $destnation['type'] == 12) {
$num *= 0.9;
}
// 부드러운 기술 제한
if(TechLimit($admin['startyear'], $year, $destnation['tech'])) { $num = intdiv($num, 4); }
$query = "update nation set totaltech=totaltech+'$num',tech=totaltech/'$destgencount' where nation='{$destnation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//양국 평균 기술가격
//$techRatio = (getTechCost($nation['tech']) + getTechCost($destnation['tech'])) / 2;
$techRatio = 1.0;
// 죽은수 도시 재정으로 누적 60%
$num = Util::round(($mykillnum+$mydeathnum) * 0.6 * $techRatio);
// 국가보정
if($destnation['type'] == 1) { $num *= 1.1; }
if($destnation['type'] == 9 || $destnation['type'] == 10) { $num *= 0.9; }
$query = "update city set dead=dead+'$num',def='{$city['def']}',wall='{$city['wall']}',agri='{$city['agri']}',comm='{$city['comm']}',secu='{$city['secu']}' where city='{$city['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 죽은수 도시 재정으로 누적 40%
$num = Util::round(($mykillnum+$mydeathnum) * 0.4 * $techRatio);
// 국가보정
if($nation['type'] == 1) { $num *= 1.1; }
if($nation['type'] == 9 || $nation['type'] == 10) { $num *= 0.9; }
$query = "update city set dead=dead+'$num' where city='{$general['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//분쟁현황에 추가
$city = addConflict($city, $general['nation'], $mykillnum);
// 병사 소진시 성 함락
if($city['def'] <= 0) {
$exp += 1000;
$exp2++;
pushGenLog($general, $log);
pushBatLog($general, $batlog);
pushBatRes($general, $batres);
pushGeneralPublicRecord($alllog, $year, $month);
pushWorldHistory($history, $year, $month);
$log = [];
$batlog = [];
$batres = [];
$alllog = [];
$history = [];
ConquerCity($admin, $general, $city, $nation, $destnation);
break;
// 공격 장수 병사 소진시 실패 처리
} elseif($general['crew'] <= 0) {
$josaYi = JosaUtil::pick($generalCrewType->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>의 {$generalCrewType->name}{$josaYi} 퇴각했습니다.";
$log[] = "<C>●</>퇴각했습니다.";
$query = "update general set deathnum=deathnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
break;
} elseif($myRice <= Util::round($general['crew']/100)) {
$josaYi = JosaUtil::pick($generalCrewType->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>의 {$generalCrewType->name}{$josaYi} 퇴각했습니다.";
$log[] = "<C>●</>군량 부족으로 퇴각합니다.";
$query = "update general set deathnum=deathnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
break;
}
// 장수 대결
} else {
$oppose = MYDB_fetch_array($result);
setLeadershipBonus($oppose, $destnation['level']);
$opposeCrewType = GameUnitConst::byId($oppose['crewtype']);
$josaYi = JosaUtil::pick($opposeCrewType->name, '이');
$josaWa = JosaUtil::pick($generalCrewType->name, '와');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>의 ".$generalCrewType->name."{$josaWa} <Y>{$oppose['name']}</>의 ".$opposeCrewType->name."{$josaYi} 대결합니다.";
$josaUl = JosaUtil::pick($opposeCrewType->name, '을');
$josaRo = JosaUtil::pick($generalCrewType->name, '로');
$log[] = "<C>●</>".$generalCrewType->name."{$josaRo} <Y>{$oppose['name']}</>의 ".$opposeCrewType->name."{$josaUl} <M>공격</>합니다.";
$josaUl = JosaUtil::pick($generalCrewType->name, '을');
$opplog[] = "<C>●</>".$opposeCrewType->name."{$josaRo} <Y>{$general['name']}</>의 ".$generalCrewType->name."{$josaUl} <M>수비</>합니다.";
$oppAtmos = 0;
if($oppose['item'] == 3) {
//탁주 사용
$oppAtmos += 3;
$query = "update general set item=0 where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$josaUl = JosaUtil::pick($oppose['item'], '을');
$opplog[] = "<C>●</><C>".getItemName($oppose['item'])."</>{$josaUl} 사용!";
$oppose['item'] = 0;
} elseif($oppose['item'] >= 14 && $oppose['item'] <= 16) {
//의적주, 두강주, 보령압주 사용
$oppAtmos += 5;
} elseif($oppose['item'] >= 19 && $oppose['item'] <= 20) {
//춘화첩, 초선화 사용
$oppAtmos += 7;
}
$oppTrain = 0;
if($oppose['item'] == 4) {
//청주 사용
$oppTrain += 3;
$query = "update general set item=0 where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$josaUl = JosaUtil::pick($oppose['item'], '을');
$opplog[] = "<C>●</><C>".getItemName($oppose['item'])."</>{$josaUl} 사용!";
$oppose['item'] = 0;
} elseif($oppose['item'] >= 12 && $oppose['item'] <= 13) {
//과실주, 이강주 사용
$oppTrain += 5;
} elseif($oppose['item'] >= 17 && $oppose['item'] <= 18) {
//철벽서, 단결도 사용
$oppTrain += 7;
}
$general['train'] += 1; //훈련 상승
if($general['train'] > GameConst::$maxTrainByWar) { $general['train'] = GameConst::$maxTrainByWar; }
$oppose['train'] += 1; //훈련 상승
if($oppose['train'] > GameConst::$maxTrainByWar) { $oppose['train'] = GameConst::$maxTrainByWar; }
$query = "update general set recwar='{$general['turntime']}',train='{$general['train']}',warnum=warnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$query = "update general set recwar='{$general['turntime']}',train='{$oppose['train']}',warnum=warnum+1 where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//특기보정 : 저격(수극), 활무기저격
$snipe = false;
$snipeItem = false;
if(!$snipe && $general['special2'] == 70 && Util::randBool(1/3)){
$snipe = true;
}
if(!$snipe && in_array($general['weap'], [10, 14, 18, 22]) && Util::randBool(1/5)){
$snipe = true;
}
if(!$snipe && $general['item'] == 2){
if(Util::randBool(1/5)){
$snipe = true;
$snipeItem = true;
}
//수극을 사용했지만 저격 실패한 케이스도 '필요하면' 넣을 것.(밸런스)
}
if($snipe) {
//수극 사용
if($snipeItem) {
$josaUl = JosaUtil::pick($general['item'], '을');
$log[] = "<C>●</><C>".getItemName($general['item'])."</>{$josaUl} 사용!";
$general['item'] = 0;
$db->update('general', ['item'=>0], 'no=%i', $general['no']);
}
$log[] = "<C>●</>상대를 <C>저격</>했다!";
$batlog[] = "<C>●</>상대를 <C>저격</>했다!";
$opplog[] = "<C>●</>상대에게 <R>저격</>당했다!";
$oppbatlog[] = "<C>●</>상대에게 <R>저격</>당했다!";
// 부상
$oppose['injury'] += rand() % 41 + 20; // 20 ~ 60
if($oppose['injury'] > 80) { $oppose['injury'] = 80; }
}
else if($snipeItem) {
$db->update('general', ['item'=>0], 'no=%i', $general['no']);
$josaYi = JosaUtil::pick($general['item'], '이');
$batlog[] = "<C>●</><C>".getItemName($general['item'])."</>{$josaYi} 빗나갑니다!";
$general['item'] = 0;
}
//특기보정 : 저격(수극), 활무기저격
$snipe = false;
$snipeItem = false;
if(!$snipe && $oppose['special2'] == 70 && Util::randBool(1/3)){
$snipe = true;
}
if(!$snipe && in_array($oppose['weap'], [10, 14, 18, 22]) && Util::randBool(1/5)){
$snipe = true;
}
if(!$snipe && $oppose['item'] == 2){
if(Util::randBool(1/5)){
$snipe = true;
$snipeItem = true;
}
//수극을 사용했지만 저격 실패한 케이스도 '필요하면' 넣을 것.(밸런스)
}
if($snipe) {
//수극 사용
if($snipeItem) {
$josaUl = JosaUtil::pick($oppose['item'], '을');
$opplog[] = "<C>●</><C>".getItemName($oppose['item'])."</>{$josaUl} 사용!";
$oppose['item'] = 0;
$db->update('general', ['item'=>0], 'no=%i', $oppose['no']);
}
$oppbatlog[] = "<C>●</>상대를 <C>저격</>했다!";
$opplog[] = "<C>●</>상대를 <C>저격</>했다!";
$batlog[] = "<C>●</>상대에게 <R>저격</>당했다!";
$log[] = "<C>●</>상대에게 <R>저격</>당했다!";
// 부상
$general['injury'] += rand() % 41 + 20; // 20 ~ 60
if($general['injury'] > 80) { $general['injury'] = 80; }
}
else if($snipeItem) {
$db->update('general', ['item'=>0], 'no=%i', $oppose['no']);
$josaYi = JosaUtil::pick($oppose['item'], '이');
$oppbatlog[] = "<C>●</><C>".getItemName($oppose['item'])."</>{$josaYi} 빗나갑니다!";
$oppose['item'] = 0;
}
$mykillnum = 0; $mydeathnum = 0;
$opkillnum = 0; $opdeathnum = 0;
while($phase < $warphase) {
$phase++;
$myAtt = $generalCrewType->getComputedAttack($general, $nation['tech']);
$myDef = $generalCrewType->getComputedDefence($general, $nation['tech']);
$opAtt = $opposeCrewType->getComputedAttack($oppose, $destnation['tech']);
$opDef = $opposeCrewType->getComputedDefence($oppose, $destnation['tech']);
// 감소할 병사 수
$myCrew = GameConst::$armperphase + $opAtt - $myDef;
$opCrew = GameConst::$armperphase + $myAtt - $opDef;
if($myCrew <= 0) { $myCrew = rand() % 90 + 10; }
if($opCrew <= 0) { $opCrew = rand() % 90 + 10; }
//훈련 사기따라
$myCrew = getCrew($myCrew, CharAtmos($oppose['atmos']+$oppAtmos+$oppAtmosBonus, $oppose['personal']), CharTrain($general['train']+$genTrain+$genTrainBonus, $general['personal']));
$opCrew = getCrew($opCrew, CharAtmos($general['atmos']+$genAtmos+$genAtmosBonus, $general['personal']), CharTrain($oppose['train']+$oppTrain+$oppTrainBonus, $oppose['personal']));
//숙련도 따라
$genDexAtt = getGenDex($general, $general['crewtype']);
$genDexDef = getGenDex($general, $oppose['crewtype']);
$oppDexAtt = getGenDex($oppose, $oppose['crewtype']);
$oppDexDef = getGenDex($oppose, $general['crewtype']);
$opCrew *= getDexLog($genDexAtt, $oppDexDef);
$myCrew *= getDexLog($oppDexAtt, $genDexDef);
$myAvoid = 1;
$opAvoid = 1;
// 병종간 특성
if($generalCrewType->magicCoef) {
$int = Util::round(getGeneralIntel($general, true, true, true, false));
$ratio2 = $int / 100 * $generalCrewType->magicCoef;
// 특기보정 : 신산
if($general['special2'] == 41) { $ratio2 += 0.2; }
if(Util::randBool($ratio2)) {
$ratio = rand() % 100;
// 특기보정 : 귀병, 신산, 환술, 신중
if($general['special2'] == 40) { $ratio += 20; }
if($general['special2'] == 41) { $ratio += 20; }
if($general['special2'] == 42) { $ratio += 10; }
if($general['special2'] == 44) { $ratio += 100; }
if($ratio >= 30) {
// 특기보정 : 환술, 집중
if($general['special2'] == 42) { $opCrew *= 1.3; }
if($general['special2'] == 43) { $opCrew *= 1.5; }
$type = rand() % 5; // 0~4
switch($type) {
case 0:
$ratio = rand() % 100;
// 특기보정 : 반계
if($oppose['special2'] == 45 && $ratio > 70) {
$batlog[] = "<C>●</><D>위보</>를 <R>역으로</> 당했다!";
$oppbatlog[] = "<C>●</><C>반계</>로 상대의 <D>위보</>를 되돌렸다!";
$myCrew *= 1.2;
} else {
$batlog[] = "<C>●</><D>위보</>를 <C>성공</>했다!";
$oppbatlog[] = "<C>●</><D>위보</>에 당했다!";
$opCrew *= 1.2;
}
break;
case 1:
$ratio = rand() % 100;
// 특기보정 : 반계
if($oppose['special2'] == 45 && $ratio > 70) {
$batlog[] = "<C>●</><D>매복</>을 <R>역으로</> 당했다!";
$oppbatlog[] = "<C>●</><C>반계</>로 상대의 <D>매복</>을 되돌렸다!";
$myCrew *= 1.4;
} else {
$batlog[] = "<C>●</><D>매복</>을 <C>성공</>했다!";
$oppbatlog[] = "<C>●</><D>매복</>에 당했다!";
$opCrew *= 1.4;
}
break;
case 2:
$ratio = rand() % 100;
// 특기보정 : 반계
if($oppose['special2'] == 45 && $ratio > 70) {
$batlog[] = "<C>●</><D>반목</>을 <R>역으로</> 당했다!";
$oppbatlog[] = "<C>●</><C>반계</>로 상대의 <D>반목</>을 되돌렸다!";
$myCrew *= 1.6;
} else {
$batlog[] = "<C>●</><D>반목</>을 <C>성공</>했다!";
$oppbatlog[] = "<C>●</><D>반목</>에 당했다!";
$opCrew *= 1.6;
// 특기보정 : 반계
if($general['special2'] == 45) { $opCrew *= 2; }
}
break;
case 3:
$ratio = rand() % 100;
// 특기보정 : 반계
if($oppose['special2'] == 45 && $ratio > 70) {
$batlog[] = "<C>●</><D>화계</>를 <R>역으로</> 당했다!";
$oppbatlog[] = "<C>●</><C>반계</>로 상대의 <D>화계</>를 되돌렸다!";
$myCrew *= 1.8;
} else {
$batlog[] = "<C>●</><D>화계</>를 <C>성공</>했다!";
$oppbatlog[] = "<C>●</><D>화계</>에 당했다!";
$opCrew *= 1.8;
}
break;
case 4:
$ratio = rand() % 100;
// 특기보정 : 반계
if($oppose['special2'] == 45 && $ratio > 70) {
$batlog[] = "<C>●</><D>혼란</>을 <R>역으로</> 당했다!";
$oppbatlog[] = "<C>●</><C>반계</>로 상대의 <D>혼란</>을 되돌렸다!";
$myCrew *= 2.0;
} else {
$batlog[] = "<C>●</><D>혼란</>을 <C>성공</>했다!";
$oppbatlog[] = "<C>●</><D>혼란</>에 당했다!";
$opCrew *= 2.0;
}
break;
}
} else {
$type = rand() % 5; // 0~4
switch($type) {
case 0:
$batlog[] = "<C>●</><D>위보</>를 <R>실패</>했다!";
$oppbatlog[] = "<C>●</><D>위보</>를 간파했다!";
$opCrew /= 1.1; $myCrew *= 1.1;
break;
case 1:
$batlog[] = "<C>●</><D>매복</>을 <R>실패</>했다!";
$oppbatlog[] = "<C>●</><D>매복</>을 간파했다!";
$opCrew /= 1.2; $myCrew *= 1.2;
break;
case 2:
$batlog[] = "<C>●</><D>반목</>을 <R>실패</>했다!";
$oppbatlog[] = "<C>●</><D>반목</>을 간파했다!";
$opCrew /= 1.3; $myCrew *= 1.3;
break;
case 3:
$batlog[] = "<C>●</><D>화계</>를 <R>실패</>했다!";
$oppbatlog[] = "<C>●</><D>화계</>를 간파했다!";
$opCrew /= 1.4; $myCrew *= 1.4;
break;
case 4:
$batlog[] = "<C>●</><D>혼란</>을 <R>실패</>했다!";
$oppbatlog[] = "<C>●</><D>혼란</>을 간파했다!";
$opCrew /= 1.5; $myCrew *= 1.5;
break;
}
}
}
}
// 상대 장수 병종간 특성
if($opposeCrewType->magicCoef) {
$int = Util::round(getGeneralIntel($oppose, true, true, true, false));
$ratio2 = $int / 100 * $opposeCrewType->magicCoef;
// 특기보정 : 신산
if($oppose['special2'] == 41) { $ratio2 += 0.2; }
if(Util::randBool($ratio2)) {
$ratio = rand() % 100;
// 특기보정 : 귀병, 신산, 환술, 신중
if($oppose['special2'] == 40) { $ratio += 20; }
if($oppose['special2'] == 41) { $ratio += 20; }
if($oppose['special2'] == 42) { $ratio += 10; }
if($oppose['special2'] == 44) { $ratio += 100; }
if($ratio >= 30) {
// 특기보정 : 환술, 집중
if($oppose['special2'] == 42) { $myCrew *= 1.3; }
if($oppose['special2'] == 43) { $myCrew *= 1.5; }
$type = rand() % 5; // 0~4
switch($type) {
case 0:
$ratio = rand() % 100;
// 특기보정 : 반계
if($general['special2'] == 45 && $ratio > 70) {
$oppbatlog[] = "<C>●</><D>위보</>를 <R>역으로</> 당했다!";
$batlog[] = "<C>●</><C>반계</>로 상대의 <D>위보</>를 되돌렸다!";
$opCrew *= 1.2;
} else {
$oppbatlog[] = "<C>●</><D>위보</>를 <C>성공</>했다!";
$batlog[] = "<C>●</><D>위보</>에 당했다!";
$myCrew *= 1.2;
}
break;
case 1:
$ratio = rand() % 100;
// 특기보정 : 반계
if($general['special2'] == 45 && $ratio > 70) {
$oppbatlog[] = "<C>●</><D>매복</>을 <R>역으로</> 당했다!";
$batlog[] = "<C>●</><C>반계</>로 상대의 <D>매복</>을 되돌렸다!";
$opCrew *= 1.4;
} else {
$oppbatlog[] = "<C>●</><D>매복</>을 <C>성공</>했다!";
$batlog[] = "<C>●</><D>매복</>에 당했다!";
$myCrew *= 1.4;
}
break;
case 2:
$ratio = rand() % 100;
// 특기보정 : 반계
if($general['special2'] == 45 && $ratio > 70) {
$oppbatlog[] = "<C>●</><D>반목</>을 <R>역으로</> 당했다!";
$batlog[] = "<C>●</><C>반계</>로 상대의 <D>반목</>을 되돌렸다!";
$opCrew *= 1.6;
} else {
$oppbatlog[] = "<C>●</><D>반목</>을 <C>성공</>했다!";
$batlog[] = "<C>●</><D>반목</>에 당했다!";
$myCrew *= 1.6;
// 특기보정 : 반계
if($oppose['special2'] == 45) { $myCrew *= 2; }
}
break;
case 3:
$ratio = rand() % 100;
// 특기보정 : 반계
if($general['special2'] == 45 && $ratio > 70) {
$oppbatlog[] = "<C>●</><D>화계</>를 <R>역으로</> 당했다!";
$batlog[] = "<C>●</><C>반계</>로 상대의 <D>화계</>을 되돌렸다!";
$opCrew *= 1.8;
} else {
$oppbatlog[] = "<C>●</><D>화계</>를 <C>성공</>했다!";
$batlog[] = "<C>●</><D>화계</>에 당했다!";
$myCrew *= 1.8;
}
break;
case 4:
$ratio = rand() % 100;
// 특기보정 : 반계
if($general['special2'] == 45 && $ratio > 70) {
$oppbatlog[] = "<C>●</><D>혼란</>을 <R>역으로</> 당했다!";
$batlog[] = "<C>●</><C>반계</>로 상대의 <D>혼란</>을 되돌렸다!";
$opCrew *= 2.0;
} else {
$oppbatlog[] = "<C>●</><D>혼란</>을 <C>성공</>했다!";
$batlog[] = "<C>●</><D>혼란</>에 당했다!";
$myCrew *= 2.0;
}
break;
}
} else {
$type = rand() % 5; // 0~4
switch($type) {
case 0:
$oppbatlog[] = "<C>●</><D>위보</>를 <R>실패</>했다!";
$batlog[] = "<C>●</><D>위보</>를 간파했다!";
$myCrew /= 1.1; $opCrew *= 1.1;
break;
case 1:
$oppbatlog[] = "<C>●</><D>매복</>을 <R>실패</>했다!";
$batlog[] = "<C>●</><D>매복</>을 간파했다!";
$myCrew /= 1.2; $opCrew *= 1.2;
break;
case 2:
$oppbatlog[] = "<C>●</><D>반목</>을 <R>실패</>했다!";
$batlog[] = "<C>●</><D>반목</>을 간파했다!";
$myCrew /= 1.3; $opCrew *= 1.3;
break;
case 3:
$oppbatlog[] = "<C>●</><D>화계</>를 <R>실패</>했다!";
$batlog[] = "<C>●</><D>화계</>를 간파했다!";
$myCrew /= 1.4; $opCrew *= 1.4;
break;
case 4:
$oppbatlog[] = "<C>●</><D>혼란</>을 <R>실패</>했다!";
$batlog[] = "<C>●</><D>혼란</>을 간파했다!";
$myCrew /= 1.5; $opCrew *= 1.5;
break;
}
}
}
}
// 특기보정: 돌격
//XXX: 목우!!!!
if($oppose['crewtype'] == 43 && $general['special2'] != 60) { // 목우
$r = 0;
$r += $oppose['atmos'] + $oppAtmos + $oppAtmosBonus;
$r += $oppose['train'] + $oppTrain + $oppTrainBonus;
$ratio = rand() % 400; // 최대 50% 저지
if($ratio < $r && $opAvoid == 1) {
$batlog[] = "<C>●</><R>저지</>당했다!</>";
$oppbatlog[] = "<C>●</>상대를 <C>저지</>했다!</>";
$opAvoid = 0;
continue;
}
}
$opCrew *= $generalCrewType->getAttackCoef($opposeCrewType);
$myCrew *= $generalCrewType->getDefenceCoef($opposeCrewType);
//군주 공격 보정 10%
if($general['level'] == 12) {
$opCrew = $opCrew * 1.10;
//참모, 장군 공격 보정 5%
} elseif($general['level'] == 11 || $general['level'] == 10 || $general['level'] == 8 || $general['level'] == 6) {
$opCrew = $opCrew * 1.05;
}
//상대장수 관직 보정
//군주 방어 보정 10%
if($oppose['level'] == 12) {
$opCrew = $opCrew * 0.90;
//참모, 모사 방어 보정 5%
} elseif($oppose['level'] == 11 || $oppose['level'] == 9 || $oppose['level'] == 7 || $oppose['level'] == 5) {
$opCrew = $opCrew * 0.95;
} elseif($oppose['level'] == 4 && $oppose['no'] == $city['gen1']) { // 태수 보정
$opCrew = $opCrew * 0.95;
} elseif($oppose['level'] == 3 && $oppose['no'] == $city['gen2']) { // 군사 보정
$opCrew = $opCrew * 0.95;
} elseif($oppose['level'] == 2 && $oppose['no'] == $city['gen3']) { // 시중 보정
$opCrew = $opCrew * 0.95;
}
//레벨 보정
$myCrew = $myCrew * (max(1, 100 - $general['explevel']/3)/100);
$opCrew = $opCrew / (max(1, 100 - $general['explevel']/3)/100);
$myCrew = $myCrew / (max(1, 100 - $oppose['explevel']/3)/100);
$opCrew = $opCrew * (max(1, 100 - $oppose['explevel']/3)/100);
// 특기보정 : 기병, 돌격, 무쌍, 보병, 견고, 척사, 의술(청낭서, 태평청령)
if($general['special2'] == 52) { $opCrew *= 1.20; }
if($general['special2'] == 60) { $opCrew *= 1.10; }
if($general['special2'] == 61) { $opCrew *= 1.10; }
if($general['special2'] == 50) { $myCrew *= 0.90; }
if($general['special2'] == 62) { $myCrew *= 0.90; }
if($general['special2'] == 75) {
if($opposeCrewType->reqCities || $opposeCrewType->reqRegions)
{
$opCrew *= 1.1; $myCrew *= 0.9;
}
}
$ratio = rand() % 100; // 0 ~ 99
if(($general['special2'] == 73 || $general['item'] == 23 || $general['item'] == 24) && $ratio > 80 && $myAvoid == 1) {
$batlog[] = "<C>●</><C>치료</>했다!</>";
$myCrew /= 1.5; // 66%만 소모
$myAvoid = 0;
}
// 상대 특기보정 : 기병, 무쌍, 보병, 견고, 척사, 의술(청낭서, 태평청령)
if($oppose['special2'] == 52) { $myCrew *= 1.10; }
if($oppose['special2'] == 61) { $myCrew *= 1.10; }
if($oppose['special2'] == 50) { $opCrew *= 0.80; }
if($oppose['special2'] == 62) { $myCrew *= 1.10; }
if($oppose['special2'] == 75) {
if($generalCrewType->reqCities || $generalCrewType->reqRegions)
{
$myCrew *= 1.1; $opCrew *= 0.9;
}
}
$ratio = rand() % 100; // 0 ~ 99
if(($oppose['special2'] == 73 || $oppose['item'] == 23 || $oppose['item'] == 24) && $ratio > 80 && $opAvoid == 1) {
$oppbatlog[] = "<C>●</><C>치료</>했다!</>";
$opCrew /= 1.5; // 66%만 소모
$opAvoid = 0;
}
//크리
$rd = rand() % 100; // 0 ~ 99
$ratio = $generalCrewType->getCriticalRatio($general);
// 특기보정 : 무쌍, 필살
if($general['special2'] == 61) { $ratio += 10; }
if($general['special2'] == 71) { $ratio += 20; }
if($ratio >= $rd && $myAvoid == 1) {
$batlog[] = "<C>●</><C>필살</>공격!</>";
$oppbatlog[] = "<C>●</>상대의 <R>필살</>공격!</>";
$opCrew = CriticalScore2($opCrew);
$myAvoid = 0;
// 특기보정 : 격노
if($oppose['special2'] == 74) {
if(rand() % 100 < 50) {
$batlog[] = "<C>●</>필살 공격에 상대가 <R>격노</>했다!</>";
$oppbatlog[] = "<C>●</>상대의 필살 공격에 <C>격노</>했다!</>";
$myCrew = CriticalScore2($myCrew);
$opAvoid = 0;
}
}
}
//크리
$rd = rand() % 100; // 0 ~ 99
$ratio = $opposeCrewType->getCriticalRatio($oppose);
// 특기보정 : 필살
if($oppose['special2'] == 71) { $ratio += 20; }
if($ratio >= $rd && $opAvoid == 1) {
$oppbatlog[] = "<C>●</><C>필살</>공격!</>";
$batlog[] = "<C>●</>상대의 <R>필살</>공격!</>";
$myCrew = CriticalScore2($myCrew);
$opAvoid = 0;
// 특기보정 : 격노
if($general['special2'] == 74) {
if(rand() % 100 < 33) {
$oppbatlog[] = "<C>●</>필살 공격에 상대가 <R>진노</>했다!</>";
$batlog[] = "<C>●</>상대의 필살 공격에 <C>진노</>했다!</>";
$opCrew = CriticalScore2($opCrew);
$myAvoid = 0;
$warphase++;
} elseif(rand() % 100 < 33) {
$oppbatlog[] = "<C>●</>필살 공격에 상대가 <R>격노</>했다!</>";
$batlog[] = "<C>●</>상대의 필살 공격에 <C>격노</>했다!</>";
$opCrew = CriticalScore2($opCrew);
$myAvoid = 0;
}
}
}
//회피
$ratio = rand() % 100; // 0 ~ 99
$ratio2 = $generalCrewType->avoid; //회피율
$ratio2 = Util::round($ratio2 * $general['train'] / 100); //훈련 반영
//특기보정 : 돌격, 궁병
if($oppose['special2'] == 60) { $ratio2 -= 100; }
if($general['special2'] == 51) { $ratio2 += 20; }
//도구 보정 : 둔갑천서, 태평요술
if($general['item'] == 26 || $general['item'] == 25) { $ratio2 += 20; }
LogText('avoid1', [date("Ymd_His"), $generalCrewType->id, $general['train'], $ratio2]);
if($ratio < $ratio2 && $myAvoid == 1) {
// 특기보정 : 격노
if($oppose['special2'] == 74 && rand() % 100 < 50) {
$batlog[] = "<C>●</>회피 시도에 상대가 <R>격노</>했다!</>";
$oppbatlog[] = "<C>●</>상대의 회피 시도에 <C>격노</>했다!</>";
$myCrew = CriticalScore2($myCrew);
$opAvoid = 0;
} else {
LogText('avoid1', true);
$batlog[] = "<C>●</><C>회피</>했다!</>";
$oppbatlog[] = "<C>●</>상대가 <R>회피</>했다!</>";
$myCrew /= 5; // 20%만 소모
$myAvoid = 0;
}
}
//회피
$ratio = rand() % 100; // 0 ~ 99
$ratio2 = $opposeCrewType->avoid; //회피율
$ratio2 = Util::round($ratio2 * $oppose['train'] / 100); //훈련 반영
// 특기보정 : 돌격, 궁병
if($general['special2'] == 60) { $ratio2 -= 100; }
if($oppose['special2'] == 51) { $ratio2 += 20; }
//도구 보정 : 둔갑천서, 태평요술
if($oppose['item'] == 26 || $oppose['item'] == 25) { $ratio2 += 20; }
LogText('avoid2', [date("Ymd_His"), $opposeCrewType->id, $oppose['train'], $ratio2]);
if($ratio < $ratio2 && $opAvoid == 1) {
// 특기보정 : 격노
if($general['special2'] == 74 && rand() % 100 < 33) {
$oppbatlog[] = "<C>●</>회피 시도에 상대가 <R>진노</>했다!</>";
$batlog[] = "<C>●</>상대의 회피 시도에 <C>진노</>했다!</>";
$opCrew = CriticalScore2($opCrew);
$myAvoid = 0;
$warphase++;
} elseif($general['special2'] == 74 && rand() % 100 < 33) {
$oppbatlog[] = "<C>●</>회피 시도에 상대가 <R>격노</>했다!</>";
$batlog[] = "<C>●</>상대의 회피 시도에 <C>격노</>했다!</>";
$opCrew = CriticalScore2($opCrew);
$myAvoid = 0;
} else {
LogText('avoid2', true);
$oppbatlog[] = "<C>●</><C>회피</>했다!</>";
$batlog[] = "<C>●</>상대가 <R>회피</>했다!</>";
$opCrew /= 5; // 20%만 소모
$opAvoid = 0;
}
}
//랜타추가
$opCrew *= (rand() % 21 + 90)/100; // 90~110%
$myCrew *= (rand() % 21 + 90)/100; // 90~110%
//특기보정 : 위압
if($general['special2'] == 63 && $phase == 1 && $general['crew'] >= 1000 && $general['atmos'] >= 90 && $general['train'] >= 90) {
$batlog[] = "<C>●</>상대에게 <C>위압</>을 줬다!</>";
$oppbatlog[] = "<C>●</>상대에게 <R>위압</>받았다!</>";
$myCrew = 0;
}
//특기보정: 위압
if($oppose['special2'] == 63 && $phase == 1 && $oppose['crew'] >= 1000 && $oppose['atmos'] >= 90 && $oppose['train'] >= 90) {
$batlog[] = "<C>●</>상대에게 <R>위압</>받았다!</>";
$oppbatlog[] = "<C>●</>상대에게 <C>위압</>을 줬다!</>";
$opCrew = 0;
}
$general['crew'] -= Util::round($myCrew);
$oppose['crew'] -= Util::round($opCrew);
$tempMyCrew = $myCrew; $tempOpCrew = $opCrew;
$tempGeneralCrew = $general['crew']; $tempOpposeCrew = $oppose['crew'];
if($general['crew'] <= 0 && $oppose['crew'] <= 0) {
$r1 = $tempGeneralCrew / $tempMyCrew;
$r2 = $tempOpposeCrew / $tempOpCrew;
if($r1 > $r2) {
$offset = Util::round($tempOpposeCrew*$tempMyCrew/$tempOpCrew);
$myCrew += $offset;
$general['crew'] -= $offset;
$opCrew += $tempOpposeCrew;
$oppose['crew'] = 0;
} else {
$offset = Util::round($tempGeneralCrew*$tempOpCrew/$tempMyCrew);
$opCrew += $offset;
$oppose['crew'] -= $offset;
$myCrew += $tempGeneralCrew;
$general['crew'] = 0;
}
} elseif($general['crew'] * $oppose['crew'] <= 0) {
if($oppose['crew'] < 0) {
$offset = Util::round($tempOpposeCrew*$tempMyCrew/$tempOpCrew);
$myCrew += $offset;
$general['crew'] -= $offset;
$opCrew += $tempOpposeCrew;
$oppose['crew'] = 0;
}
if($general['crew'] < 0) {
$offset = Util::round($tempGeneralCrew*$tempOpCrew/$tempMyCrew);
$opCrew += $offset;
$oppose['crew'] -= $offset;
$myCrew += $tempGeneralCrew;
$general['crew'] = 0;
}
}
$exp += $opCrew;
$opexp += $myCrew;
$general['crew'] = Util::round($general['crew']);
$oppose['crew'] = Util::round($oppose['crew']);
$myCrew = Util::round($myCrew);
$opCrew = Util::round($opCrew);
$batlog[] = "<C>●</> $phase : <Y1>【{$general['name']}】</> <C>{$general['crew']} (-$myCrew)</> VS <C>{$oppose['crew']} (-$opCrew)</> <Y1>【{$oppose['name']}】</>";
$oppbatlog[] = "<C>●</> $phase : <Y1>【{$oppose['name']}】</> <C>{$oppose['crew']} (-$opCrew)</> VS <C>{$general['crew']} (-$myCrew)</> <Y1>【{$general['name']}】</>";
$mykillnum += $opCrew; $mydeathnum += $myCrew;
$opkillnum += $myCrew; $opdeathnum += $opCrew;
// 중간 쌀 체크
$myRice = Util::round($exp / 50);
// 성격 보정
$myRice = CharExperience($myRice, $general['personal']);
// 쌀 소모
$myRice = ($myRice * 5 * getCrewtypeRice($generalCrewType, $nation['tech']));
// 결과 쌀
$myRice = $general['rice'] - $myRice;
// 중간 쌀 체크
$opRice = Util::round($opexp / 50 * 0.8);
// 성격 보정
$opRice = CharExperience($opRice, $oppose['personal']);
// 쌀 소모
$opRice = ($opRice * 5 * getCrewtypeRice($opposeCrewType, $destnation['tech']));
// 결과 쌀
$opRice = $oppose['rice'] - $opRice;
if($opRice <= Util::round($oppose['crew']/100)) { break; }
if($myRice <= Util::round($general['crew']/100)) { break; }
if($oppose['crew'] <= 0) { break; }
if($general['crew'] <= 0) { break; }
}
$render_attacker = [
'crewtype' => mb_substr($generalCrewType->name, 0, 2),
'name'=> $general['name'],
'remain_crew' => $general['crew'],
'killed_crew' => -$mydeathnum
];
$render_defender = [
'crewtype' => mb_substr($opposeCrewType->name, 0, 2),
'name'=> $oppose['name'],
'remain_crew' => $oppose['crew'],
'killed_crew' => -$opdeathnum
];
$res = str_replace(["\r\n", "\r", "\n"], '', $templates->render('small_war_log',[
'year'=>$year,
'month'=>$month,
'war_type'=>'attack',
'war_type_str'=>'→',
'me' => $render_attacker,
'you' => $render_defender,
]));
$oppres = str_replace(["\r\n", "\r", "\n"], '', $templates->render('small_war_log',[
'year'=>$year,
'month'=>$month,
'war_type'=>'defense',
'war_type_str'=>'←',
'me' => $render_defender,
'you' => $render_attacker,
]));
$log[] = $res;
$batlog[] = $res;
$batres[] = $res;
$opplog[] = $oppres;
$oppbatlog[] = $oppres;
$oppbatres[] = $oppres;
$deadAmount['att'] = $deadAmount['att'] + $mydeathnum;
$deadAmount['def'] = $deadAmount['def'] + $opdeathnum;
// 상대장수 부상
$ratio = rand() % 100;
if($ratio >= 95) {
$opplog[] = "<C>●</>전투중 <R>부상</>당했다!";
$oppose['injury'] += rand() % 71 + 10; // 10 ~ 80
if($oppose['injury'] > 80) { $oppose['injury'] = 80; }
}
// 병사수 변경
$query = "update general set injury='{$oppose['injury']}',crew='{$oppose['crew']}',killcrew=killcrew+'$opkillnum',deathcrew=deathcrew+'$opdeathnum' where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 숙련도 증가
addGenDex($oppose['no'], $general['atmos'], $general['train'], $oppose['crewtype'], $opkillnum * 0.9);
addGenDex($oppose['no'], $general['atmos'], $general['train'], $general['crewtype'], $opdeathnum * 0.9);
// 죽은수 기술로 누적
$num = Util::round($mydeathnum * 0.01);
// 국가보정
if($nation['type'] == 3 || $nation['type'] == 13) { $num *= 1.1; }
if($nation['type'] == 5 || $nation['type'] == 6 || $nation['type'] == 7 || $nation['type'] == 8 || $nation['type'] == 12) { $num *= 0.9; }
// 부드러운 기술 제한
if(TechLimit($admin['startyear'], $year, $nation['tech'])) { $num = intdiv($num, 4); }
$query = "update nation set totaltech=totaltech+'$num',tech=totaltech/'$gencount' where nation='{$nation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 장수 부상
$ratio = rand() % 100;
if($ratio >= 95) {
$log[] = "<C>●</>전투중 <R>부상</>당했다!";
$general['injury'] += rand() % 71 + 10; // 10 ~ 80
if($general['injury'] > 80) { $general['injury'] = 80; }
}
// 병사수 변경
$query = "update general set injury='{$general['injury']}',crew='{$general['crew']}',killcrew=killcrew+'$mykillnum',deathcrew=deathcrew+'$mydeathnum' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 숙련도 증가
addGenDex($general['no'], $general['atmos'], $general['train'], $general['crewtype'], $mykillnum);
addGenDex($general['no'], $general['atmos'], $general['train'], $oppose['crewtype'], $mydeathnum);
// 죽은수 기술로 누적
$num = Util::round($opdeathnum * 0.01);
// 국가보정
if($destnation['type'] == 3 || $destnation['type'] == 13) { $num *= 1.1; }
if($destnation['type'] == 5 || $destnation['type'] == 6 || $destnation['type'] == 7 || $destnation['type'] == 8 || $destnation['type'] == 12) { $num *= 0.9; }
// 부드러운 기술 제한
if(TechLimit($admin['startyear'], $year, $destnation['tech'])) { $num = intdiv($num, 4); }
$query = "update nation set totaltech=totaltech+'$num',tech=totaltech/'$destgencount' where nation='{$destnation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//양국 평균 기술가격
//$techRatio = (getTechCost($nation['tech']) + getTechCost($destnation['tech'])) / 2;
$techRatio = 1.0;
// 죽은수 도시 재정으로 누적 60%
$num = Util::round(($mykillnum+$mydeathnum) * 0.6 * $techRatio);
// 국가보정
if($destnation['type'] == 1) { $num *= 1.1; }
if($destnation['type'] == 9 || $destnation['type'] == 10) { $num *= 0.9; }
$query = "update city set dead=dead+'$num' where city='{$city['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 죽은수 도시 재정으로 누적 40%
$num = Util::round(($mykillnum+$mydeathnum) * 0.4 * $techRatio);
// 국가보정
if($nation['type'] == 1) { $num *= 1.1; }
if($nation['type'] == 9 || $nation['type'] == 10) { $num *= 0.9; }
$query = "update city set dead=dead+'$num' where city='{$general['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 상대 병사 소진이나 쌀 소진시 다음 장수
if($oppose['crew'] <= 0 || ($opRice <= Util::round($oppose['crew']/100) && $general['crew'] > 0)) {
if($opRice <= Util::round($oppose['crew']/100)) {
$josaYi = JosaUtil::pick($opposeCrewType->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$oppose['name']}</>의 {$opposeCrewType->name}{$josaYi} 패퇴했습니다.";
$log[] = "<C>●</><Y>{$oppose['name']}</>의 {$opposeCrewType->name}{$josaYi} 패퇴했습니다.";
$opplog[] = "<C>●</>군량 부족으로 패퇴합니다.";
} else {
$josaYi = JosaUtil::pick($opposeCrewType->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$oppose['name']}</>의 {$opposeCrewType->name}{$josaYi} 전멸했습니다.";
$log[] = "<C>●</><Y>{$oppose['name']}</>의 {$opposeCrewType->name}{$josaYi} 전멸했습니다.";
$opplog[] = "<C>●</>전멸했습니다.";
}
$opposecount--;
$general['atmos'] *= 1.1; //사기 증가
if($general['atmos'] > GameConst::$maxAtmosByWar) { $general['atmos'] = GameConst::$maxAtmosByWar; }
$query = "update general set atmos='{$general['atmos']}',killnum=killnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$exp2++;
// 상대장수 경험 등등 증가
$opexp = Util::round($opexp / 50 * 0.8);
// 성격 보정
$opexp = CharExperience($opexp, $oppose['personal']);
// 쌀 소모
$oppose['rice'] -= ($opexp * 5 * getCrewtypeRice($opposeCrewType, $destnation['tech']));
if($oppose['rice'] < 0) { $oppose['rice'] = 0; }
$query = "update general set deathnum=deathnum+1,rice='{$oppose['rice']}',experience=experience+'$opexp',dedication=dedication+'$opexp' where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$opexp = 0;
pushGenLog($oppose, $opplog);
pushBatLog($oppose, $oppbatlog);
pushBatRes($oppose, $oppbatres);
$oppose = null;
$opplog = [];
$oppbatlog = [];
$oppbatres = [];
// 공격 장수 병사 소진이나 쌀 소진시 실패 처리
} elseif($general['crew'] <= 0 || $myRice <= Util::round($general['crew']/100)) {
if($myRice <= Util::round($general['crew']/100)) {
$josaYi = JosaUtil::pick($generalCrewType->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>의 {$generalCrewType->name}{$josaYi} 퇴각했습니다.";
$log[] = "<C>●</>군량 부족으로 퇴각합니다.";
$opplog[] = "<C>●</><Y>{$general['name']}</>의 {$generalCrewType->name}{$josaYi} 퇴각했습니다.";
} else {
$josaYi = JosaUtil::pick($generalCrewType->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>의 {$generalCrewType->name}{$josaYi} 퇴각했습니다.";
$log[] = "<C>●</>퇴각했습니다.";
$opplog[] = "<C>●</><Y>{$general['name']}</>의 {$generalCrewType->name}{$josaYi} 퇴각했습니다.";
}
// 경험치 상승
if($opposeCrewType->armType == GameUnitConst::T_WIZARD) { // 귀병
$oppose['intel2']++;
} elseif($opposeCrewType->armType == GameUnitConst::T_SIEGE) { // 차병
$oppose['leader2']++;
} else {
$oppose['power2']++;
}
$oppose['atmos'] *= 1.1; //사기 증가
if($oppose['atmos'] > GameConst::$maxAtmosByWar) { $oppose['atmos'] = GameConst::$maxAtmosByWar; }
// 상대장수 경험 등등 증가
$opexp = Util::round($opexp / 50 * 0.8);
// 성격 보정
$opexp = CharExperience($opexp, $oppose['personal']);
// 쌀 소모
$oppose['rice'] -= ($opexp * 5 * getCrewtypeRice($opposeCrewType, $destnation['tech']));
if($oppose['rice'] < 0) { $oppose['rice'] = 0; }
$query = "update general set rice='{$oppose['rice']}',leader2='{$oppose['leader2']}',power2='{$oppose['power2']}',intel2='{$oppose['intel2']}',atmos='{$oppose['atmos']}',experience=experience+'$opexp',dedication=dedication+'$opexp',killnum=killnum+1 where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$query = "update general set deathnum=deathnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$opexp = 0;
$opplog = checkAbility($oppose, $opplog);
pushGenLog($oppose, $opplog);
pushBatLog($oppose, $oppbatlog);
pushBatRes($oppose, $oppbatres);
$opplog = [];
$oppbatlog = [];
$oppbatres = [];
// $josaYi = JosaUtil::pick($general['name'], '이');
// $alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>{$josaYi} }<G>{$city['name']}</> 공략에 실패했습니다. <1>$date</>";
// $log[] = "<C>●</> <G>{$city['name']}</> 공략에 실패했습니다. <1>$date</>";
break;
} else {
// 무승부일때 로그 남김
pushGenLog($oppose, $opplog);
pushBatLog($oppose, $oppbatlog);
pushBatRes($oppose, $oppbatres);
$opplog = [];
$oppbatlog = [];
$oppbatres = [];
}
}
}
if(isset($oppose)){
//마지막 페이즈에 장수가 전멸하지 않은 경우. 쌀 소모 후속 처리
// 상대장수 경험 등등 증가(페이즈 초과시)
$opexp = Util::round($opexp / 50 * 0.8);
// 성격 보정
$opexp = CharExperience($opexp, $oppose['personal']);
// 쌀 소모
$oppose['rice'] -= ($opexp * 5 * getCrewtypeRice($opposeCrewType, $destnation['tech']));
if($oppose['rice'] < 0) { $oppose['rice'] = 0; }
$query = "update general set rice='{$oppose['rice']}',experience=experience+'$opexp',dedication=dedication+'$opexp' where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
}
// 경험치 상승
if($generalCrewType->armType == GameUnitConst::T_WIZARD) { // 귀병
$general['intel2'] += $exp2;
} elseif($generalCrewType->armType == GameUnitConst::T_SIEGE) { // 차병
$general['leader2'] += $exp2;
} else {
$general['power2'] += $exp2;
}
$query = "update general set leader2='{$general['leader2']}',power2='{$general['power2']}',intel2='{$general['intel2']}' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 공헌, 명성 상승
$exp = Util::round($exp / 50);
// 성격 보정
$exp = CharExperience($exp, $general['personal']);
// 쌀 소모
$general['rice'] -= ($exp * 5 * getCrewtypeRice($generalCrewType, $nation['tech']));
if($general['rice'] < 0) { $general['rice'] = 0; }
$query = "update general set rice='{$general['rice']}',dedication=dedication+'$exp',experience=experience+'$exp' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$log = checkAbility($general, $log);
pushGenLog($general, $log);
pushBatLog($general, $batlog);
pushBatRes($general, $batres);
pushGeneralPublicRecord($alllog, $year, $month);
pushWorldHistory($history);
return $deadAmount;
}
function CriticalScore2($score) {
$score = Util::round($score * (rand()%8 + 13)/10); // 1.3~2.0
return $score;
}
//0 0 : 100 100 이면 최고 무한대 차이
//30 30 : 100 100 이면 최고 3.3배 차이
//60 60 : 100 100 이면 최고 1.6배 차이
function getCrew($crew, $youatmos, $mytrain) {
$ratio = $youatmos / $mytrain;
$crew = $crew * $ratio;
return $crew;
}
function getCrewtypeRice($crewtype, $tech) {
$cost = $crewtype->rice / 10;
return $cost * getTechCost($tech);
}
//////////////////////////////////////////////////////////////
// 표준 공 / 수 반환 수치는 약 0이 되게 (100~550)
//////////////////////////////////////////////////////////////
function addConflict($city, $nationID, $mykillnum) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$nationlist = [];
$killnum = [0];
list($year, $month) = $gameStor->getValuesAsArray(['year', 'month']);
$conflict = Json::decode($city['conflict']);
if(!$conflict || $city['def'] == 0){ // 선타, 막타 보너스
$mykillnum *= 1.05;
}
if (!$conflict) {
$conflict[$nationID] = $mykillnum;
}
else if(key_exists($nationID, $conflict)){
$conflict[$nationID] += $mykillnum;
arsort($conflict);
}
else{
$conflict[$nationID] = $mykillnum;
arsort($conflict);
$nation = getNationStaticInfo($nationID);
$josaYi = JosaUtil::pick($nation['name'], '이');
pushWorldHistory(["<C>●</>{$year}{$month}월:<M><b>【분쟁】</b></><D><b>{$nation['name']}</b></>{$josaYi} <G><b>{$city['name']}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다."]);
}
$rawConflict = Json::encode($conflict);
$city['conflict'] = $rawConflict;
$db->update('city', [
'conflict'=>$rawConflict
], 'city=%i',$city['city']);
return $city;
}
function DeleteConflict($nation) {
$db = DB::db();
foreach($db->queryAllLists('SELECT city, conflict FROM city WHERE conflict!=%s', '{}') as list($cityID, $rawConflict)){
$conflict = Json::decode($rawConflict);
if(!$conflict || !is_array($conflict)){
continue;
}
if(!key_exists($nation, $conflict)){
continue;
}
unset($conflict[$nation]);
$db->update('city', [
'conflict'=>Json::encode($conflict)
], 'city=%i', $cityID);
}
}
function getConquerNation($city) : int {
$conflict = Json::decode($city['conflict']);
return Util::array_first_key($conflict);
}
function ConquerCity($admin, $general, $city, $nation, $destnation) {
'@phan-var array<string,mixed> $city';
$db = DB::db();
$connect=$db->get();
$alllog = [];
$log = [];
$history = [];
if($destnation['nation'] > 0) {
$destnationName = "<D><b>{$destnation['name']}</b></>의";
} else {
$destnationName = "공백지인";
}
$year = $admin['year'];
$month = $admin['month'];
$josaUl = JosaUtil::pick($city['name'], '을');
$josaYiNation = JosaUtil::pick($nation['name'], '이');
$josaYiGen = JosaUtil::pick($general['name'], '이');
$josaYiCity = JosaUtil::pick($city['name'], '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>{$josaYiGen} <G><b>{$city['name']}</b></> 공략에 <S>성공</>했습니다.";
$log[] = "<C>●</><G><b>{$city['name']}</b></> 공략에 <S>성공</>했습니다.";
$history[] = "<C>●</>{$year}{$month}월:<S><b>【지배】</b></><D><b>{$nation['name']}</b></>{$josaYiNation} <G><b>{$city['name']}</b></>{$josaUl} 지배했습니다.";
pushGeneralHistory($general, "<C>●</>{$year}{$month}월:<G><b>{$city['name']}</b></>{$josaUl} <S>함락</>시킴");
pushNationHistory($nation, "<C>●</>{$year}{$month}월:<Y>{$general['name']}</>{$josaYiGen} {$destnationName} <G><b>{$city['name']}</b></>{$josaUl} <S>점령</>");
pushNationHistory($destnation, "<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 <Y>{$general['name']}</>에 의해 <G><b>{$city['name']}</b></>{$josaYiCity} <span class='ev_highlight'>함락</span>");
$query = "select city from city where nation='{$city['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$citycount = MYDB_num_rows($result);
// 국가 멸망시
//TODO: 국가 멸망 코드를 별도로 작성
if($citycount == 1 && $city['nation'] != 0) {
$query = "select nation,name,gold,rice from nation where nation='{$city['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$losenation = MYDB_fetch_array($result);
$josaYi = JosaUtil::pick($losenation['name'], '이');
$josaUl = JosaUtil::pick($losenation['name'], '을');
$history[] = "<C>●</>{$year}{$month}월:<R><b>【멸망】</b></><D><b>{$losenation['name']}</b></>{$josaYi} 멸망하였습니다.";
pushNationHistory($nation, "<C>●</>{$year}{$month}월:<D><b>{$losenation['name']}</b></>{$josaUl} 정복");
$query = "select no, nation from general where nation='{$general['nation']}' and level='12'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$ruler = MYDB_fetch_array($result);
//다굴치는 나라들 전방설정을 위해 미리 얻어옴
$query = "select you from diplomacy where me='{$losenation['nation']}' and state<2";
$dipResult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$dipCount = MYDB_num_rows($dipResult);
$loseGeneralGold = 0;
$loseGeneralRice = 0;
//멸망국 장수들 역사 기록 및 로그 전달
$josaYi = JosaUtil::pick($losenation['name'], '이');
$genlog = ["<C>●</><D><b>{$losenation['name']}</b></>{$josaYi} <R>멸망</>했습니다."];
// 국가 백업
$oldNation = $db->queryFirstRow('SELECT * FROM nation WHERE nation=%i', $city['nation']);
$oldNationGenerals = $db->query('SELECT * FROM general WHERE nation=%i', $city['nation']);
$oldNation['generals'] = array_map(function($gen){
//다른 코드와는 다르게 공용으로 쓰므로 남겨둠
return $gen['no'];
}, $oldNationGenerals);
$oldNation['aux'] = Json::decode($oldNation['aux']);
foreach($oldNationGenerals as $gen){
$loseGold = intdiv($gen['gold'] * (rand()%30+20), 100);
$loseRice = intdiv($gen['rice'] * (rand()%30+20), 100);
$genlog[1] = "<C>●</>도주하며 금<C>$loseGold</> 쌀<C>$loseRice</>을 분실했습니다.";
$query = "update general set gold=gold-{$loseGold},rice=rice-{$loseRice} where no={$gen['no']}";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
pushGenLog($gen, $genlog);
pushGeneralHistory($gen, "<C>●</>{$year}{$month}월:<D><b>{$losenation['name']}</b></>{$josaYi} <R>멸망</>");
pushOldNationStop($gen['no'], $city['nation']);
$loseGeneralGold += $loseGold;
$loseGeneralRice += $loseRice;
//모두 등용장 발부
if($nation['name'] == "강족" || $nation['name'] == "저족" || $nation['name'] == "흉노족"
|| $nation['name'] == "남만족" || $nation['name'] == "산월족" || $nation['name'] == "오환족"
|| $nation['name'] == "왜족") {
//등용장 미발부
} elseif(Util::randBool(0.5)) {
$msg = ScoutMessage::buildScoutMessage($general['no'], $gen['no']);
if($msg){
$msg->send(true);
}
}
//NPC인 경우 10% 확률로 임관(엔장, 인재, 의병)
if($gen['npc'] >= 2 && $gen['npc'] <= 8 && rand() % 100 < 10) {
$commissionCommand = EncodeCommand(0, 0, $nation['nation'], 25); //임관
$query = "update general set turn0='$commissionCommand' where no={$gen['no']}";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
}
}
unset($genlog[1]);
// 승전국 보상
$losenation['gold'] -= GameConst::$basegold;
$losenation['rice'] -= GameConst::$baserice;
if($losenation['gold'] < 0) { $losenation['gold'] = 0; }
if($losenation['rice'] < 0) { $losenation['rice'] = 0; }
$losenation['gold'] += $loseGeneralGold;
$losenation['rice'] += $loseGeneralRice;
$losenation['gold'] = intdiv($losenation['gold'], 2);
$losenation['rice'] = intdiv($losenation['gold'], 2);
// 기본량 제외 금쌀50% + 장수들 분실 금쌀50% 흡수
$query = "update nation set gold=gold+'{$losenation['gold']}',rice=rice+'{$losenation['rice']}' where nation='{$general['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//아국 수뇌부에게 로그 전달
$query = "select no,name,nation from general where nation='{$general['nation']}' and level>='9'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$gencount = MYDB_num_rows($result);
$genlog[0] = "<C>●</><D><b>{$losenation['name']}</b></> 정복으로 금<C>{$losenation['gold']}</> 쌀<C>{$losenation['rice']}</>을 획득했습니다.";
for($i=0; $i < $gencount; $i++) {
$gen = MYDB_fetch_array($result);
pushGenLog($gen, $genlog);
}
//분쟁기록 모두 지움
DeleteConflict($city['nation']);
// 전 장수 공헌 명성치 깎음
$query = "update general set dedication=dedication*0.5,experience=experience*0.9 where nation='{$city['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 전 도시 공백지로
$query = "update city set nation='0',gen1='0',gen2='0',gen3='0',conflict='{}',term=0 where nation='{$city['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 전 장수 소속 무소속으로, 재야로, 부대 탈퇴
$query = "update general set nation='0',belong='0',level='0',troop='0' where nation='{$city['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 부대도 삭제
$query = "delete from troop where nation='{$city['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 외교 삭제
$query = "delete from diplomacy where me='{$city['nation']}' or you='{$city['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$db->insert('ng_old_nations', [
'server_id'=>UniqueConst::$serverID,
'nation'=>$city['nation'],
'data'=>Json::encode($oldNation)
]);
// 국가 삭제
$query = "delete from nation where nation='{$city['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 아까 얻어온 다굴국들 전방설정
for($i=0; $i < $dipCount; $i++) {
$dip = MYDB_fetch_array($dipResult);
//전방설정
SetNationFront($dip['you']);
}
// 멸망이 아니면
} else {
// 태수,군사,시중은 일반으로...
$db->update('general',[
'level'=>1
], 'no IN %li',[$city['gen1'], $city['gen2'], $city['gen3']]);
//수도였으면 긴급 천도
if(isset($destnation['capital']) && $destnation['capital'] == $city['city']) {
$minCity = findNextCapital($city['city'], $destnation['nation']);
$minCityName = CityConst::byID($minCity)->name;
$josaYi = JosaUtil::pick($destnation['name'], '이');
$history[] = "<C>●</>{$year}{$month}월:<M><b>【긴급천도】</b></><D><b>{$destnation['name']}</b></>{$josaYi} 수도가 함락되어 <G><b>$minCityName</b></>으로 긴급천도하였습니다.";
//아국 수뇌부에게 로그 전달
$query = "select no,name,nation from general where nation='{$destnation['nation']}' and level>='5'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$gencount = MYDB_num_rows($result);
$genlog = ["<C>●</>수도가 함락되어 <G><b>$minCityName</b></>으로 <M>긴급천도</>합니다."];
for($i=0; $i < $gencount; $i++) {
$gen = MYDB_fetch_array($result);
pushGenLog($gen, $genlog);
}
//천도
$query = "update nation set capital='$minCity',gold=gold*0.5,rice=rice*0.5 where nation='{$destnation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//보급도시로 만듬
$query = "update city set supply=1 where city='$minCity'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//수뇌부 이동
$query = "update general set city='$minCity' where nation='{$destnation['nation']}' and level>='5'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//장수 사기 감소
$query = "update general set atmos=atmos*0.8 where nation='{$destnation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
refreshNationStaticInfo();
}
}
$general['atmos'] *= 1.1; //사기 증가
if($general['atmos'] > GameConst::$maxAtmosByWar) { $general['atmos'] = GameConst::$maxAtmosByWar; }
$conquerNation = getConquerNation($city);
if($conquerNation == $general['nation']) {
// 이동 및 사기 변경
$query = "update general set city='{$city['city']}',atmos='{$general['atmos']}',killnum=killnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
if($city['level'] > 3) {
// 도시 소속 변경, 태수,군사,시중 초기화
$query = "update city set supply=1,conflict='{}',term=0,agri=agri*0.7,comm=comm*0.7,secu=secu*0.7,def=1000,wall=1000,nation='{$general['nation']}',gen1=0,gen2=0,gen3=0 where city='{$city['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
} else {
// 도시 소속 변경, 태수,군사,시중 초기화
$query = "update city set supply=1,conflict='{}',term=0,agri=agri*0.7,comm=comm*0.7,secu=secu*0.7,def=def2/2,wall=wall2/2,nation='{$general['nation']}',gen1=0,gen2=0,gen3=0 where city='{$city['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
}
//전방설정
SetNationFront($nation['nation']);
SetNationFront($destnation['nation']);
} else {
$query = "select name,nation from nation where nation='$conquerNation'";
$conquerResult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$conquerNationArray = MYDB_fetch_array($conquerResult);
$josaUl = JosaUtil::pick($city['name'], '을');
$josaYi = JosaUtil::pick($conquerNationArray['name'], '이');
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【분쟁협상】</b></><D><b>{$conquerNationArray['name']}</b></>{$josaYi} 영토분쟁에서 우위를 점하여 <G><b>{$city['name']}</b></>{$josaUl} 양도받았습니다.";
pushNationHistory($nation, "<C>●</>{$year}{$month}월:<G><b>{$city['name']}</b></>{$josaUl} <D><b>{$conquerNationArray['name']}</b></>에 <Y>양도</>");
pushNationHistory($conquerNationArray, "<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>에서 <G><b>{$city['name']}</b></>{$josaUl} <S>양도</> 받음");
// 이동X 및 사기 변경
$query = "update general set atmos='{$general['atmos']}',killnum=killnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$query = [
'supply'=>1,
'term'=>0,
'conflict'=>'{}',
'agri'=>$db->sqleval('agri*0.7'),
'comm'=>$db->sqleval('comm*0.7'),
'secu'=>$db->sqleval('secu*0.7'),
'nation'=>$conquerNation,
'gen1'=>0,
'gen2'=>0,
'gen3'=>0
];
if($city['level'] > 3) {
$query['def'] = 1000;
$query['wall'] = 1000;
} else {
// 도시 소속 변경, 태수,군사,시중 초기화
$query['def'] = $db->sqleval('def2/2');
$query['wall'] = $db->sqleval('wall2/2');
}
$db->update('city', $query, 'city=%i', (int)$city['city']);
//전방설정
SetNationFront($destnation['nation']);
SetNationFront($conquerNation);
}
pushGenLog($general, $log);
pushGeneralPublicRecord($alllog, $year, $month);
pushWorldHistory($history);
}
function findNextCapital(int $capitalID, int $nationID):int{
$distList = searchDistance($capitalID, 99, true);
$cities = [];
foreach(
DB::db()->query(
'SELECT city, pop FROM city WHERE nation=%i and city!=%i',
$nationID,
$capitalID
) as $row
){
$cities[$row['city']] = $row['pop'];
};
foreach($distList as $dist=>$distSubList){
$maxCityPop = 0;
$minCity = 0;
foreach($distSubList as $cityID){
if(!key_exists($cityID, $cities)){
continue;
}
$cityPop = $cities[$cityID];
if($cityPop < $maxCityPop){
continue;
}
$minCity = $cityID;
$maxCityPop = $cityPop;
}
if($minCity){
return $minCity;
}
}
throw new \RuntimeException('도시가 남지 않았는데 긴천을 시도하고 있습니다');
}
+405 -1725
View File
@@ -2,1724 +2,419 @@
namespace sammo;
function processWar($general, $city) {
'@phan-var array<string,int|string|null> $general';
function processWar(array $rawAttacker, array $rawDefenderCity){
$db = DB::db();
$rawAttackerCity = $db->queryFirstRow('SELECT * FROM city WHERE city = %i', $rawAttacker['city']);
$attackerNationID = $rawAttacker['nation'];
$defenderNationID = $rawDefenderCity['nation'];
$rawAttackerNation = $db->queryFirstRow('SELECT nation,`level`,`name`,capital,totaltech,gennum,tech,`type`,gold,rice FROM nation WHERE nation = %i', $attackerNationID);
if($defenderNationID == 0){
$rawDefenderNation = [
'nation'=>0,
'name'=>'재야',
'capital'=>0,
'level'=>0,
'gold'=>0,
'rice'=>2000,
'type'=>0,
'tech'=>0,
'totaltech'=>0,
'gennum'=>1
];
}
else{
$rawDefenderNation = $db->queryFirstRow('SELECT nation,`level`,`name`,capital,totaltech,gennum,tech,`type`,gold,rice FROM nation WHERE nation = %i', $defenderNationID);
}
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
[$startYear, $year, $month, $cityRate] = $gameStor->getValuesAsArray(['startyear', 'year', 'month', 'city_rate']);
$templates = new \League\Plates\Engine(__dir__.'/templates');
$attacker = new WarUnitGeneral($rawAttacker, $rawAttackerCity, $rawAttackerNation, true, $year, $month);
$date = substr($general['turntime'],11,5);
$city = new WarUnitCity($rawDefenderCity, $rawAttackerNation, $year, $month, $cityRate);
$admin = $gameStor->getAll();
$defenderList = $db->query('SELECT no,name,nation,turntime,personal,special2,crew,crewtype,atmos,train,intel,intel2,book,power,power2,weap,injury,leader,leader2,horse,item,explevel,experience,dedication,level,gold,rice,dex0,dex10,dex20,dex30,dex40,warnum,killnum,deathnum,killcrew,deathcrew,recwar FROM general WHERE nation=%i AND city=%i AND nation!=0 and crew > 0 and rice>(crew/100) and ((train>=60 and atmos>=60 and mode=1) or (train>=80 and atmos>=80 and mode=2))', $city->getVar('nation'), $city->getVar('city'));
$year = $admin['year'];
$month = $admin['month'];
$log = [];
$batlog = [];
$batres = [];
$opplog = [];
$oppbatlog = [];
$oppbatres = [];
$alllog = [];
$history = [];
$deadAmount = [
'att'=>0,
'def'=>0
];
$warphase = GameUnitConst::byID($general['crewtype'])->speed; //병종간 페이즈 수 얻기
// 특기보정 : 돌격
if($general['special2'] == 60) { $warphase += 1; }
$genAtmos = 0;
if($general['item'] == 3) {
//탁주 사용
$genAtmos += 3;
$query = "update general set item=0 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$josaUl = JosaUtil::pick($general['item'], '을');
$log[] = "<C>●</><C>".getItemName($general['item'])."</>{$josaUl} 사용!";
$general['item'] = 0;
} elseif($general['item'] >= 14 && $general['item'] <= 16) {
//의적주, 두강주, 보령압주 사용
$genAtmos += 5;
} elseif($general['item'] >= 19 && $general['item'] <= 20) {
//춘화첩, 초선화 사용
$genAtmos += 7;
}
$genTrain = 0;
if($general['item'] == 4) {
//청주 사용
$genTrain += 3;
$query = "update general set item=0 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$josaUl = JosaUtil::pick($general['item'], '을');
$log[] = "<C>●</><C>".getItemName($general['item'])."</>{$josaUl} 사용!";
$general['item'] = 0;
} elseif($general['item'] >= 12 && $general['item'] <= 13) {
//과실주, 이강주 사용
$genTrain += 5;
} elseif($general['item'] >= 17 && $general['item'] <= 18) {
//철벽서, 단결도 사용
$genTrain += 7;
if(!$defenderList){
$defenderList = [];
}
// 우선 스케일링
$city['def'] *= 10;
$city['wall'] *= 10;
$query = "select level from city where city='{$general['city']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$originCity = MYDB_fetch_array($result);
$query = "select nation,level,name,capital,tech,type from nation where nation='{$general['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$nation = MYDB_fetch_array($result);
$query = "select nation,level,name,rice,capital,tech,type from nation where nation='{$city['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$destnation = MYDB_fetch_array($result) ?: [
'nation'=>0,
'capital'=>0,
'level'=>0,
'rice'=>2000,
'type'=>0,
'tech'=>0
];
//장수수 구함
$query = "select no from general where nation='{$general['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$gencount = MYDB_num_rows($result);
if($gencount < GameConst::$initialNationGenLimit) $gencount = GameConst::$initialNationGenLimit;
//장수수 구함
$query = "select no from general where nation='{$destnation['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$destgencount = MYDB_num_rows($result);
if($destgencount < GameConst::$initialNationGenLimit) $destgencount = GameConst::$initialNationGenLimit;
$genAtmosBonus = 0; $genTrainBonus = 0;
$oppAtmosBonus = 0; $oppTrainBonus = 0;
//공격자 수도보정
if($nation['capital'] == $general['city']) { $genAtmosBonus += 5; }
//방어자 수도보정
//if($destnation['capital'] == $city['city']) { $oppTrainBonus += 5; }
//관,진,수진 보정
if($city['level'] == 1) { $oppTrainBonus += 5; } // 방어도시가 수진이면 방어자 방어보정
if($originCity['level'] == 2) { $genAtmosBonus += 5; } // 출병도시가 진이면 공격자 공격보정
if($city['level'] == 3) { $oppTrainBonus += 5; } // 방어도시가 관이면 방어자 방어보정
$josaRo = JosaUtil::pick($city['name'], '로');
$josaYi = JosaUtil::pick($general['name'], '이');
$alllog[] = "<C>●</>{$month}월:<D><b>{$nation['name']}</b></>의 <Y>{$general['name']}</>{$josaYi} <G><b>{$city['name']}</b></>{$josaRo} 진격합니다.";
$log[] = "<C>●</>{$month}월:<G><b>{$city['name']}</b></>{$josaRo} <M>진격</>합니다. <1>$date</>";
// 목표 도시내에 목표 국가 소속 장수 중, 병사가 있는 능력치합+병사수 순으로 훈,사 60, 80 이상
$query = "select no,name,turntime,personal,special2,crew,crewtype,atmos,train,intel,intel2,book,power,power2,weap,injury,leader,leader2,horse,item,explevel,level,rice,leader+power+intel+weap+horse+book+crew/100 as sum,dex0,dex10,dex20,dex30,dex40 from general where city='{$city['city']}' and nation='{$city['nation']}' and nation!=0 and crew>'0' and rice>round(crew/100) and ((train>=60 and atmos>=60 and mode=1) or (train>=80 and atmos>=80 and mode=2)) order by sum desc";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$opposecount = MYDB_num_rows($result);
$exp = 0; //병사 소진 시킨 만큼
$opexp = 0;
$exp2 = 1; //능력경험치
$phase = 0;
while($phase < $warphase) {
// 장수가 없어서 도시 공격하려했으나 병량없을시
if($opposecount == 0 && $destnation['nation'] > 0 && $destnation['rice'] <= 0 && $city['supply'] == 1) {
$general['train'] += 1; //훈련 상승
if($general['train'] > GameConst::$maxTrainByWar) { $general['train'] = GameConst::$maxTrainByWar; }
$query = "update general set recwar='{$general['turntime']}',train='{$general['train']}',warnum=warnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$alllog[] = "<C>●</>{$month}월:병량 부족으로 <G><b>{$city['name']}</b></>의 수비병들이 <R>패퇴</>합니다.";
$josaUl = JosaUtil::pick($city['name'], '을');
$josaYi = JosaUtil::pick($general['name'], '이');
$history[] = "<C>●</>{$year}{$month}월:<M><b>【패퇴】</b></><D><b>{$destnation['name']}</b></>{$josaYi} 병량 부족으로 <G><b>{$city['name']}</b></>{$josaUl} 뺏기고 말았습니다.";
pushGenLog($general, $log);
pushGeneralPublicRecord($alllog, $year, $month);
pushWorldHistory($history);
$log = [];
$alllog = [];
$history= [];
//패퇴시 병량보충
$destnation['rice'] += 500;
$query = "update nation set rice='{$destnation['rice']}' where nation='{$destnation['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//내정 피폐
$query = "update city set agri=agri*0.5,comm=comm*0.5,secu=secu*0.5 where city='{$city['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$city = addConflict($city, $general['nation'], 1);//NOTE: 이 경우 두 국가가 분쟁 중인 경우에는 병량패퇴의 이득이 없다.
ConquerCity($admin, $general, $city, $nation, $destnation);
break;
// 장수가 없어서 도시 공격
} elseif($opposecount == 0) {
$josaRo = JosaUtil::pick(GameUnitConst::byId($general['crewtype'])->name, '로');
$josaYi = JosaUtil::pick($general['name'], '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>{$josaYi} ".GameUnitConst::byId($general['crewtype'])->name."{$josaRo} 성벽을 공격합니다.";
$log[] = "<C>●</>".GameUnitConst::byId($general['crewtype'])->name."{$josaRo} 성벽을 <M>공격</>합니다.";
$general['train'] += 1; //훈련 상승
if($general['train'] > GameConst::$maxTrainByWar) { $general['train'] = GameConst::$maxTrainByWar; }
$query = "update general set recwar='{$general['turntime']}',train='{$general['train']}',warnum=warnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$mykillnum = 0; $mydeathnum = 0;
while($phase < $warphase) {
$phase++;
if($general['level'] == 12) {
$lbonus = $nation['level'] * 2;
} elseif($general['level'] >= 5) {
$lbonus = $nation['level'];
} else {
$lbonus = 0;
}
$myAtt = getAtt($general, $nation['tech'], $lbonus);
$myDef = getDef($general, $nation['tech']);
$cityAtt = getCityAtt($city);
$cityDef = getCityDef($city);
// 감소할 병사 수
$cityCrew = GameConst::$armperphase + $myAtt - $cityDef;
$myCrew = GameConst::$armperphase + $cityAtt - $myDef;
if($cityCrew <= 0) { $cityCrew = rand() % 90 + 10; }
if($myCrew <= 0) { $myCrew = rand() % 90 + 10; }
//훈련 사기따라
$myCrew = getCrew($myCrew, $admin['city_rate']+$oppAtmosBonus, CharTrain($general['train']+$genTrain+$genTrainBonus, $general['personal']));
$cityCrew = getCrew($cityCrew, CharAtmos($general['atmos']+$genAtmos+$genAtmosBonus, $general['personal']), $admin['city_rate']+$oppTrainBonus);
//숙련도 따라
$genDexAtt = getGenDex($general, $general['crewtype']);
$genDexDef = getGenDex($general, 40);
$cityCrew *= getDexLog($genDexAtt, ($admin['city_rate']-60)*7200);
$myCrew *= getDexLog(($admin['city_rate']-60)*7200, $genDexDef);
$avoid = 1;
// 병종간 특성
if(intdiv($general['crewtype'], 10) == 3) { // 귀병
$int = Util::round(getGeneralIntel($general, true, true, true, false));
if($general['crewtype'] == 30) {
$ratio2 = $int * 5; // 0~500 즉 50%
} elseif($general['crewtype'] == 31) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($general['crewtype'] == 32) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($general['crewtype'] == 33) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($general['crewtype'] == 34) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($general['crewtype'] == 35) {
$ratio2 = $int * 8; // 0~800 즉 80%
} elseif($general['crewtype'] == 36) {
$ratio2 = $int * 8; // 0~800 즉 80%
} elseif($general['crewtype'] == 37) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($general['crewtype'] == 38) {
$ratio2 = $int * 6; // 0~600 즉 60%
}
// 특기보정 : 신산
if($general['special2'] == 41) { $ratio2 += 200; }
$ratio = rand() % 1000; // 0~999
if($ratio <= $ratio2) {
$ratio = rand() % 100; // 0~99
// 특기보정 : 귀병, 신산, 환술, 신중
if($general['special2'] == 40) { $ratio += 20; }
if($general['special2'] == 41) { $ratio += 20; }
if($general['special2'] == 42) { $ratio += 10; }
if($general['special2'] == 44) { $ratio += 100; }
if($ratio >= 30) {
// 특기보정 : 환술, 집중
if($general['special2'] == 42) { $cityCrew *= 1.3; }
if($general['special2'] == 43) { $cityCrew *= 1.5; }
$type = rand() % 3;
switch($type) {
case 0:
$batlog[] = "<C>●</><D>급습</>을 <C>성공</>했다!";
$cityCrew *= 1.2;
break;
case 1:
$batlog[] = "<C>●</><D>위보</>를 <C>성공</>했다!";
$cityCrew *= 1.4;
break;
case 2:
$batlog[] = "<C>●</><D>혼란</>을 <C>성공</>했다!";
$cityCrew *= 1.6;
break;
}
} else {
$type = rand() % 3;
switch($type) {
case 0:
$batlog[] = "<C>●</><D>급습</>을 <R>실패</>했다!";
$cityCrew /= 1.2; $myCrew *= 1.2;
break;
case 1:
$batlog[] = "<C>●</><D>위보</>를 <R>실패</>했다!";
$cityCrew /= 1.4; $myCrew *= 1.4;
break;
case 2:
$batlog[] = "<C>●</><D>혼란</>을 <R>실패</>했다!";
$cityCrew /= 1.6; $myCrew *= 1.6;
break;
}
}
}
} elseif($general['crewtype'] == 40) { // 정란
$cityCrew = $cityCrew * 1.8;
} elseif($general['crewtype'] == 41) { // 충차
$cityCrew = $cityCrew * 2.4;
} elseif($general['crewtype'] == 42) { // 벽력거
$cityCrew = $cityCrew * 1.8;
}
//군주 공격 보정 10%
if($general['level'] == 12) {
$cityCrew = $cityCrew * 1.10;
//참모, 장군 공격 보정 5%
} elseif($general['level'] == 11 || $general['level'] == 10 || $general['level'] == 8 || $general['level'] == 6) {
$cityCrew = $cityCrew * 1.05;
}
//레벨 보정
$cityCrew = $cityCrew * (100 + $general['explevel']/6)/100;
// 특기보정 : 공성, 기병, 돌격, 무쌍, 보병, 견고, 의술(청낭서,태평청령)
if($general['special2'] == 53) { $cityCrew *= 2.00; }
if($general['special2'] == 52) { $cityCrew *= 1.20; }
if($general['special2'] == 60) { $cityCrew *= 1.10; }
if($general['special2'] == 61) { $cityCrew *= 1.10; }
if($general['special2'] == 50) { $myCrew *= 0.90; }
if($general['special2'] == 62) { $myCrew *= 0.90; }
$ratio = rand() % 100; // 0 ~ 99
if(($general['special2'] == 73 || $general['item'] == 23 || $general['item'] == 24) && $ratio > 80 && $avoid == 1) {
$batlog[] = "<C>●</><C>치료</>했다!</>";
$myCrew /= 1.5; // 66%만 소모
$avoid = 0;
}
//크리
$rd = rand() % 100; // 0 ~ 99
$ratio = CriticalRatio3($general);
// 특기보정 : 무쌍, 필살
if($general['special2'] == 61) { $ratio += 10; }
if($general['special2'] == 71) { $ratio += 20; }
if($ratio >= $rd && $avoid == 1) {
$batlog[] = "<C>●</><C>필살</>공격!</>";
$cityCrew = CriticalScore2($cityCrew);
$avoid = 0;
}
//회피
$ratio = rand() % 100; // 0 ~ 99
$ratio2 = GameUnitConst::byID($general['crewtype'])->avoid; //회피율
$ratio2 = Util::round($ratio2 * $general['train'] / 100); //훈련 반영
//특기보정 : 궁병
if($general['special2'] == 51) { $ratio2 += 20; }
//도구 보정 : 둔갑천서, 태평요술
if($general['item'] == 26 || $general['item'] == 25) { $ratio2 += 20; }
if($ratio < $ratio2 && $avoid == 1) {
$batlog[] = "<C>●</><C>회피</>했다!</>";
$myCrew /= 5; // 20%만 소모
$avoid = 0;
}
//랜타추가
$cityCrew *= (rand() % 21 + 90)/100; // 90~110%
$myCrew *= (rand() % 21 + 90)/100; // 90~110%
//특기보정 : 위압
if($general['special2'] == 63 && $phase == 1 && $general['crew'] >= 1000 && $general['atmos'] >= 90 && $general['train'] >= 90) {
$batlog[] = "<C>●</>상대에게 <C>위압</>을 줬다!</>";
$myCrew = 0;
}
$general['crew'] -= Util::round($myCrew);
$city['def'] -= Util::round($cityCrew);
$city['wall'] -= Util::round($cityCrew);
$tempMyCrew = $myCrew; $tempCityCrew = $cityCrew;
$tempGeneralCrew = $general['crew']; $tempCityDef = $city['def'];
if($city['wall'] <= 0) { $city['wall'] = 0; }
if($general['crew'] <= 0 && $city['def'] <= 0) {
$r1 = $tempGeneralCrew / $tempMyCrew;
$r2 = $tempCityDef / $tempCityCrew;
if($r1 > $r2) {
$offset = Util::round($tempCityDef*$tempMyCrew/$tempCityCrew);
$myCrew += $offset;
$general['crew'] -= $offset;
$cityCrew += $tempCityDef;
$city['def'] = 0;
} else {
$offset = Util::round($tempGeneralCrew*$tempCityCrew/$tempMyCrew);
$cityCrew += $offset;
$city['def'] -= $offset;
$myCrew += $tempGeneralCrew;
$general['crew'] = 0;
}
} elseif($general['crew'] * $city['def'] <= 0) {
if($city['def'] < 0) {
$offset = Util::round($tempCityDef*$tempMyCrew/$tempCityCrew);
$myCrew += $offset;
$general['crew'] -= $offset;
$cityCrew += $tempCityDef;
$city['def'] = 0;
}
if($general['crew'] < 0) {
$offset = Util::round($tempGeneralCrew*$tempCityCrew/$tempMyCrew);
$cityCrew += $offset;
$city['def'] -= $offset;
$myCrew += $tempGeneralCrew;
$general['crew'] = 0;
}
}
$exp += $cityCrew;
$opexp += $myCrew;
$general['crew'] = Util::round($general['crew']);
$cityCrew = Util::round($cityCrew);
$myCrew = Util::round($myCrew);
$batlog[] = "<C>●</> $phase : <Y1>【{$general['name']}】</> <C>{$general['crew']} (-$myCrew)</> VS <C>{$city['def']} (-$cityCrew)</> <Y1>【{$city['name']}】</>";
$mykillnum += $cityCrew; $mydeathnum += $myCrew;
// 중간 쌀 체크
$myRice = Util::round($exp / 50);
// 성격 보정
$myRice = CharExperience($myRice, $general['personal']);
// 쌀 소모
$myRice = ($myRice * 5 * getCrewtypeRice($general['crewtype'], $nation['tech']));
// 결과 쌀
$myRice = $general['rice'] - $myRice;
if($myRice <= Util::round($general['crew']/100)) { break; }
if($city['def'] <= 0) { break; }
if($general['crew'] <= 0) { break; }
}
$render_attacker = [
'crewtype' => mb_substr(GameUnitConst::byId($general['crewtype'])->name, 0, 2),
'name'=> $general['name'],
'remain_crew' => $general['crew'],
'killed_crew' => -$mydeathnum
];
$render_defender = [
'crewtype' => '성벽',
'name'=> $city['name'],
'remain_crew' => $city['def'],
'killed_crew' => -$mykillnum
];
$res = str_replace(["\r\n", "\r", "\n"], '', $templates->render('small_war_log',[
'year'=>$year,
'month'=>$month,
'war_type'=>'siege',
'war_type_str'=>'→',
'me' => $render_attacker,
'you' => $render_defender,
]));
$log[] = $res;//TODO: $log를 출력할 때 date에 대해선 숨겨야 함.
$batlog[] = $res;
$batres[] = $res;
$deadAmount['att'] = $deadAmount['att'] + $mydeathnum;
$deadAmount['def'] = $deadAmount['def'] + $mykillnum;
// 도시쌀 소모 계산
$opexp = Util::round($opexp / 50 * 0.8);
$rice = Util::round($opexp * 5 * getCrewtypeRice(0, 0) * ($admin['city_rate']/100 - 0.2));
$destnation['rice'] -= $rice;
if($destnation['rice'] < 0) { $destnation['rice'] = 0; }
$query = "update nation set rice='{$destnation['rice']}' where nation='{$destnation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
pushAdminLog(["성벽 쌀 소모 : $rice"]);
//원래대로 스케일링
$city['def'] = Util::round($city['def'] / 10);
$city['wall'] = Util::round($city['wall'] / 10);
//내정 감소
$dec = Util::round($cityCrew / 10);
$city['agri'] -= $dec;
$city['comm'] -= $dec;
$city['secu'] -= $dec;
if($city['agri'] < 0) { $city['agri'] = 0; }
if($city['comm'] < 0) { $city['comm'] = 0; }
if($city['secu'] < 0) { $city['secu'] = 0; }
// 병사수 변경
$query = "update general set crew='{$general['crew']}',killcrew=killcrew+'$mykillnum',deathcrew=deathcrew+'$mydeathnum' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 숙련도 증가
addGenDex($general['no'], $general['atmos'], $general['train'], $general['crewtype'], $mykillnum);
addGenDex($general['no'], $general['atmos'], $general['train'], 40, $mydeathnum);
// 죽은수 기술로 누적
$num = Util::round($mydeathnum * 0.01);
// 국가보정
if($nation['type'] == 3 || $nation['type'] == 13) { $num *= 1.1; }
if($nation['type'] == 5 || $nation['type'] == 6 || $nation['type'] == 7 || $nation['type'] == 8 || $nation['type'] == 12) { $num *= 0.9; }
// 부드러운 기술 제한
if(TechLimit($admin['startyear'], $year, $nation['tech'])) { $num = intdiv($num, 4); }
$query = "update nation set totaltech=totaltech+'$num',tech=totaltech/'$gencount' where nation='{$nation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 죽은수 기술로 누적
$num = Util::round($mykillnum * 0.01);
// 국가보정
if($destnation['type'] == 3 || $destnation['type'] == 13){
$num *= 1.1;
}
if($destnation['type'] == 5 || $destnation['type'] == 6 || $destnation['type'] == 7 || $destnation['type'] == 8 || $destnation['type'] == 12) {
$num *= 0.9;
}
// 부드러운 기술 제한
if(TechLimit($admin['startyear'], $year, $destnation['tech'])) { $num = intdiv($num, 4); }
$query = "update nation set totaltech=totaltech+'$num',tech=totaltech/'$destgencount' where nation='{$destnation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//양국 평균 기술가격
//$techRatio = (getTechCost($nation['tech']) + getTechCost($destnation['tech'])) / 2;
$techRatio = 1.0;
// 죽은수 도시 재정으로 누적 60%
$num = Util::round(($mykillnum+$mydeathnum) * 0.6 * $techRatio);
// 국가보정
if($destnation['type'] == 1) { $num *= 1.1; }
if($destnation['type'] == 9 || $destnation['type'] == 10) { $num *= 0.9; }
$query = "update city set dead=dead+'$num',def='{$city['def']}',wall='{$city['wall']}',agri='{$city['agri']}',comm='{$city['comm']}',secu='{$city['secu']}' where city='{$city['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 죽은수 도시 재정으로 누적 40%
$num = Util::round(($mykillnum+$mydeathnum) * 0.4 * $techRatio);
// 국가보정
if($nation['type'] == 1) { $num *= 1.1; }
if($nation['type'] == 9 || $nation['type'] == 10) { $num *= 0.9; }
$query = "update city set dead=dead+'$num' where city='{$general['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//분쟁현황에 추가
$city = addConflict($city, $general['nation'], $mykillnum);
// 병사 소진시 성 함락
if($city['def'] <= 0) {
$exp += 1000;
$exp2++;
pushGenLog($general, $log);
pushBatLog($general, $batlog);
pushBatRes($general, $batres);
pushGeneralPublicRecord($alllog, $year, $month);
pushWorldHistory($history, $year, $month);
$log = [];
$batlog = [];
$batres = [];
$alllog = [];
$history = [];
ConquerCity($admin, $general, $city, $nation, $destnation);
break;
// 공격 장수 병사 소진시 실패 처리
} elseif($general['crew'] <= 0) {
$josaYi = JosaUtil::pick(GameUnitConst::byId($general['crewtype'])->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>의 ".GameUnitConst::byId($general['crewtype'])->name."{$josaYi} 퇴각했습니다.";
$log[] = "<C>●</>퇴각했습니다.";
$query = "update general set deathnum=deathnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
break;
} elseif($myRice <= Util::round($general['crew']/100)) {
$josaYi = JosaUtil::pick(GameUnitConst::byId($general['crewtype'])->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>의 ".GameUnitConst::byId($general['crewtype'])->name."{$josaYi} 퇴각했습니다.";
$log[] = "<C>●</>군량 부족으로 퇴각합니다.";
$query = "update general set deathnum=deathnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
break;
}
// 장수 대결
} else {
$oppose = MYDB_fetch_array($result);
$josaYi = JosaUtil::pick(GameUnitConst::byId($oppose['crewtype'])->name, '이');
$josaWa = JosaUtil::pick(GameUnitConst::byId($general['crewtype'])->name, '와');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>의 ".GameUnitConst::byId($general['crewtype'])->name."{$josaWa} <Y>{$oppose['name']}</>의 ".GameUnitConst::byId($oppose['crewtype'])->name."{$josaYi} 대결합니다.";
$josaUl = JosaUtil::pick(GameUnitConst::byId($oppose['crewtype'])->name, '을');
$josaRo = JosaUtil::pick(GameUnitConst::byId($general['crewtype'])->name, '로');
$log[] = "<C>●</>".GameUnitConst::byId($general['crewtype'])->name."{$josaRo} <Y>{$oppose['name']}</>의 ".GameUnitConst::byId($oppose['crewtype'])->name."{$josaUl} <M>공격</>합니다.";
$josaUl = JosaUtil::pick(GameUnitConst::byId($general['crewtype'])->name, '을');
$opplog[] = "<C>●</>".GameUnitConst::byId($oppose['crewtype'])->name."{$josaRo} <Y>{$general['name']}</>의 ".GameUnitConst::byId($general['crewtype'])->name."{$josaUl} <M>수비</>합니다.";
$oppAtmos = 0;
if($oppose['item'] == 3) {
//탁주 사용
$oppAtmos += 3;
$query = "update general set item=0 where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$josaUl = JosaUtil::pick($oppose['item'], '을');
$opplog[] = "<C>●</><C>".getItemName($oppose['item'])."</>{$josaUl} 사용!";
$oppose['item'] = 0;
} elseif($oppose['item'] >= 14 && $oppose['item'] <= 16) {
//의적주, 두강주, 보령압주 사용
$oppAtmos += 5;
} elseif($oppose['item'] >= 19 && $oppose['item'] <= 20) {
//춘화첩, 초선화 사용
$oppAtmos += 7;
}
$oppTrain = 0;
if($oppose['item'] == 4) {
//청주 사용
$oppTrain += 3;
$query = "update general set item=0 where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$josaUl = JosaUtil::pick($oppose['item'], '을');
$opplog[] = "<C>●</><C>".getItemName($oppose['item'])."</>{$josaUl} 사용!";
$oppose['item'] = 0;
} elseif($oppose['item'] >= 12 && $oppose['item'] <= 13) {
//과실주, 이강주 사용
$oppTrain += 5;
} elseif($oppose['item'] >= 17 && $oppose['item'] <= 18) {
//철벽서, 단결도 사용
$oppTrain += 7;
}
$general['train'] += 1; //훈련 상승
if($general['train'] > GameConst::$maxTrainByWar) { $general['train'] = GameConst::$maxTrainByWar; }
$oppose['train'] += 1; //훈련 상승
if($oppose['train'] > GameConst::$maxTrainByWar) { $oppose['train'] = GameConst::$maxTrainByWar; }
$query = "update general set recwar='{$general['turntime']}',train='{$general['train']}',warnum=warnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$query = "update general set recwar='{$general['turntime']}',train='{$oppose['train']}',warnum=warnum+1 where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//특기보정 : 저격(수극), 활무기저격
$snipe = false;
$snipeItem = false;
if(!$snipe && $general['special2'] == 70 && Util::randBool(1/3)){
$snipe = true;
}
if(!$snipe && in_array($general['weap'], [10, 14, 18, 22]) && Util::randBool(1/5)){
$snipe = true;
}
if(!$snipe && $general['item'] == 2){
if(Util::randBool(1/5)){
$snipe = true;
$snipeItem = true;
}
//수극을 사용했지만 저격 실패한 케이스도 '필요하면' 넣을 것.(밸런스)
}
if($snipe) {
//수극 사용
if($snipeItem) {
$josaUl = JosaUtil::pick($general['item'], '을');
$log[] = "<C>●</><C>".getItemName($general['item'])."</>{$josaUl} 사용!";
$general['item'] = 0;
$db->update('general', ['item'=>0], 'no=%i', $general['no']);
}
$log[] = "<C>●</>상대를 <C>저격</>했다!";
$batlog[] = "<C>●</>상대를 <C>저격</>했다!";
$opplog[] = "<C>●</>상대에게 <R>저격</>당했다!";
$oppbatlog[] = "<C>●</>상대에게 <R>저격</>당했다!";
// 부상
$oppose['injury'] += rand() % 41 + 20; // 20 ~ 60
if($oppose['injury'] > 80) { $oppose['injury'] = 80; }
}
else if($snipeItem) {
$db->update('general', ['item'=>0], 'no=%i', $general['no']);
$josaYi = JosaUtil::pick($general['item'], '이');
$batlog[] = "<C>●</><C>".getItemName($general['item'])."</>{$josaYi} 빗나갑니다!";
$general['item'] = 0;
}
//특기보정 : 저격(수극), 활무기저격
$snipe = false;
$snipeItem = false;
if(!$snipe && $oppose['special2'] == 70 && Util::randBool(1/3)){
$snipe = true;
}
if(!$snipe && in_array($oppose['weap'], [10, 14, 18, 22]) && Util::randBool(1/5)){
$snipe = true;
}
if(!$snipe && $oppose['item'] == 2){
if(Util::randBool(1/5)){
$snipe = true;
$snipeItem = true;
}
//수극을 사용했지만 저격 실패한 케이스도 '필요하면' 넣을 것.(밸런스)
}
if($snipe) {
//수극 사용
if($snipeItem) {
$josaUl = JosaUtil::pick($oppose['item'], '을');
$log[] = "<C>●</><C>".getItemName($oppose['item'])."</>{$josaUl} 사용!";
$oppose['item'] = 0;
$db->update('general', ['item'=>0], 'no=%i', $oppose['no']);
}
$oppbatlog[] = "<C>●</>상대를 <C>저격</>했다!";
$opplog[] = "<C>●</>상대를 <C>저격</>했다!";
$batlog[] = "<C>●</>상대에게 <R>저격</>당했다!";
$log[] = "<C>●</>상대에게 <R>저격</>당했다!";
// 부상
$general['injury'] += rand() % 41 + 20; // 20 ~ 60
if($general['injury'] > 80) { $general['injury'] = 80; }
}
else if($snipeItem) {
$db->update('general', ['item'=>0], 'no=%i', $oppose['no']);
$josaYi = JosaUtil::pick($oppose['item'], '이');
$batlog[] = "<C>●</><C>".getItemName($oppose['item'])."</>{$josaYi} 빗나갑니다!";
$oppose['item'] = 0;
}
$mykillnum = 0; $mydeathnum = 0;
$opkillnum = 0; $opdeathnum = 0;
while($phase < $warphase) {
$phase++;
if($general['level'] == 12) {
$lbonus = $nation['level'] * 2;
} elseif($general['level'] >= 5) {
$lbonus = $nation['level'];
} else {
$lbonus = 0;
}
$myAtt = getAtt($general, $nation['tech'], $lbonus);
$myDef = getDef($general, $nation['tech']);
if($oppose['level'] == 12) {
$opplbonus = $destnation['level'] * 2;
} elseif($oppose['level'] >= 5) {
$opplbonus = $destnation['level'];
} else {
$opplbonus = 0;
}
$opAtt = getAtt($oppose, $destnation['tech'], $opplbonus);
$opDef = getDef($oppose, $destnation['tech']);
// 감소할 병사 수
$myCrew = GameConst::$armperphase + $opAtt - $myDef;
$opCrew = GameConst::$armperphase + $myAtt - $opDef;
if($myCrew <= 0) { $myCrew = rand() % 90 + 10; }
if($opCrew <= 0) { $opCrew = rand() % 90 + 10; }
//훈련 사기따라
$myCrew = getCrew($myCrew, CharAtmos($oppose['atmos']+$oppAtmos+$oppAtmosBonus, $oppose['personal']), CharTrain($general['train']+$genTrain+$genTrainBonus, $general['personal']));
$opCrew = getCrew($opCrew, CharAtmos($general['atmos']+$genAtmos+$genAtmosBonus, $general['personal']), CharTrain($oppose['train']+$oppTrain+$oppTrainBonus, $oppose['personal']));
//숙련도 따라
$genDexAtt = getGenDex($general, $general['crewtype']);
$genDexDef = getGenDex($general, $oppose['crewtype']);
$oppDexAtt = getGenDex($oppose, $oppose['crewtype']);
$oppDexDef = getGenDex($oppose, $general['crewtype']);
$opCrew *= getDexLog($genDexAtt, $oppDexDef);
$myCrew *= getDexLog($oppDexAtt, $genDexDef);
$myAvoid = 1;
$opAvoid = 1;
// 병종간 특성
if(intdiv($general['crewtype'], 10) == 3) { // 귀병
$int = Util::round(getGeneralIntel($general, true, true, true, false));
if($general['crewtype'] == 30) {
$ratio2 = $int * 5; // 0~500 즉 50%
} elseif($general['crewtype'] == 31) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($general['crewtype'] == 32) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($general['crewtype'] == 33) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($general['crewtype'] == 34) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($general['crewtype'] == 35) {
$ratio2 = $int * 8; // 0~800 즉 80%
} elseif($general['crewtype'] == 36) {
$ratio2 = $int * 8; // 0~800 즉 80%
} elseif($general['crewtype'] == 37) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($general['crewtype'] == 38) {
$ratio2 = $int * 6; // 0~600 즉 60%
}
// 특기보정 : 신산
if($general['special2'] == 41) { $ratio2 += 200; }
$ratio = rand() % 1000; // 0~999
if($ratio <= $ratio2) {
$ratio = rand() % 100;
// 특기보정 : 귀병, 신산, 환술, 신중
if($general['special2'] == 40) { $ratio += 20; }
if($general['special2'] == 41) { $ratio += 20; }
if($general['special2'] == 42) { $ratio += 10; }
if($general['special2'] == 44) { $ratio += 100; }
if($ratio >= 30) {
// 특기보정 : 환술, 집중
if($general['special2'] == 42) { $opCrew *= 1.3; }
if($general['special2'] == 43) { $opCrew *= 1.5; }
$type = rand() % 5; // 0~4
switch($type) {
case 0:
$ratio = rand() % 100;
// 특기보정 : 반계
if($oppose['special2'] == 45 && $ratio > 70) {
$batlog[] = "<C>●</><D>위보</>를 <R>역으로</> 당했다!";
$oppbatlog[] = "<C>●</><C>반계</>로 상대의 <D>위보</>를 되돌렸다!";
$myCrew *= 1.2;
} else {
$batlog[] = "<C>●</><D>위보</>를 <C>성공</>했다!";
$oppbatlog[] = "<C>●</><D>위보</>에 당했다!";
$opCrew *= 1.2;
}
break;
case 1:
$ratio = rand() % 100;
// 특기보정 : 반계
if($oppose['special2'] == 45 && $ratio > 70) {
$batlog[] = "<C>●</><D>매복</>을 <R>역으로</> 당했다!";
$oppbatlog[] = "<C>●</><C>반계</>로 상대의 <D>매복</>을 되돌렸다!";
$myCrew *= 1.4;
} else {
$batlog[] = "<C>●</><D>매복</>을 <C>성공</>했다!";
$oppbatlog[] = "<C>●</><D>매복</>에 당했다!";
$opCrew *= 1.4;
}
break;
case 2:
$ratio = rand() % 100;
// 특기보정 : 반계
if($oppose['special2'] == 45 && $ratio > 70) {
$batlog[] = "<C>●</><D>반목</>을 <R>역으로</> 당했다!";
$oppbatlog[] = "<C>●</><C>반계</>로 상대의 <D>반목</>을 되돌렸다!";
$myCrew *= 1.6;
} else {
$batlog[] = "<C>●</><D>반목</>을 <C>성공</>했다!";
$oppbatlog[] = "<C>●</><D>반목</>에 당했다!";
$opCrew *= 1.6;
// 특기보정 : 반계
if($general['special2'] == 45) { $opCrew *= 2; }
}
break;
case 3:
$ratio = rand() % 100;
// 특기보정 : 반계
if($oppose['special2'] == 45 && $ratio > 70) {
$batlog[] = "<C>●</><D>화계</>를 <R>역으로</> 당했다!";
$oppbatlog[] = "<C>●</><C>반계</>로 상대의 <D>화계</>를 되돌렸다!";
$myCrew *= 1.8;
} else {
$batlog[] = "<C>●</><D>화계</>를 <C>성공</>했다!";
$oppbatlog[] = "<C>●</><D>화계</>에 당했다!";
$opCrew *= 1.8;
}
break;
case 4:
$ratio = rand() % 100;
// 특기보정 : 반계
if($oppose['special2'] == 45 && $ratio > 70) {
$batlog[] = "<C>●</><D>혼란</>을 <R>역으로</> 당했다!";
$oppbatlog[] = "<C>●</><C>반계</>로 상대의 <D>혼란</>을 되돌렸다!";
$myCrew *= 2.0;
} else {
$batlog[] = "<C>●</><D>혼란</>을 <C>성공</>했다!";
$oppbatlog[] = "<C>●</><D>혼란</>에 당했다!";
$opCrew *= 2.0;
}
break;
}
} else {
$type = rand() % 5; // 0~4
switch($type) {
case 0:
$batlog[] = "<C>●</><D>위보</>를 <R>실패</>했다!";
$oppbatlog[] = "<C>●</><D>위보</>를 간파했다!";
$opCrew /= 1.1; $myCrew *= 1.1;
break;
case 1:
$batlog[] = "<C>●</><D>매복</>을 <R>실패</>했다!";
$oppbatlog[] = "<C>●</><D>매복</>을 간파했다!";
$opCrew /= 1.2; $myCrew *= 1.2;
break;
case 2:
$batlog[] = "<C>●</><D>반목</>을 <R>실패</>했다!";
$oppbatlog[] = "<C>●</><D>반목</>을 간파했다!";
$opCrew /= 1.3; $myCrew *= 1.3;
break;
case 3:
$batlog[] = "<C>●</><D>화계</>를 <R>실패</>했다!";
$oppbatlog[] = "<C>●</><D>화계</>를 간파했다!";
$opCrew /= 1.4; $myCrew *= 1.4;
break;
case 4:
$batlog[] = "<C>●</><D>혼란</>을 <R>실패</>했다!";
$oppbatlog[] = "<C>●</><D>혼란</>을 간파했다!";
$opCrew /= 1.5; $myCrew *= 1.5;
break;
}
}
}
}
// 상대 장수 병종간 특성
if(intdiv($oppose['crewtype'], 10) == 3) { // 귀병
$int = Util::round(getGeneralIntel($oppose, true, true, true, false));
if($oppose['crewtype'] == 30) {
$ratio2 = $int * 5; // 0~500 즉 50%
} elseif($oppose['crewtype'] == 31) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($oppose['crewtype'] == 32) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($oppose['crewtype'] == 33) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($oppose['crewtype'] == 34) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($oppose['crewtype'] == 35) {
$ratio2 = $int * 8; // 0~800 즉 80%
} elseif($oppose['crewtype'] == 36) {
$ratio2 = $int * 8; // 0~800 즉 80%
} elseif($oppose['crewtype'] == 37) {
$ratio2 = $int * 6; // 0~600 즉 60%
} elseif($oppose['crewtype'] == 38) {
$ratio2 = $int * 6; // 0~600 즉 60%
}
// 특기보정 : 신산
if($oppose['special2'] == 41) { $ratio2 += 200; }
$ratio = rand() % 1000; // 0~999
if($ratio <= $ratio2) {
$ratio = rand() % 100;
// 특기보정 : 귀병, 신산, 환술, 신중
if($oppose['special2'] == 40) { $ratio += 20; }
if($oppose['special2'] == 41) { $ratio += 20; }
if($oppose['special2'] == 42) { $ratio += 10; }
if($oppose['special2'] == 44) { $ratio += 100; }
if($ratio >= 30) {
// 특기보정 : 환술, 집중
if($oppose['special2'] == 42) { $myCrew *= 1.3; }
if($oppose['special2'] == 43) { $myCrew *= 1.5; }
$type = rand() % 5; // 0~4
switch($type) {
case 0:
$ratio = rand() % 100;
// 특기보정 : 반계
if($general['special2'] == 45 && $ratio > 70) {
$oppbatlog[] = "<C>●</><D>위보</>를 <R>역으로</> 당했다!";
$batlog[] = "<C>●</><C>반계</>로 상대의 <D>위보</>를 되돌렸다!";
$opCrew *= 1.2;
} else {
$oppbatlog[] = "<C>●</><D>위보</>를 <C>성공</>했다!";
$batlog[] = "<C>●</><D>위보</>에 당했다!";
$myCrew *= 1.2;
}
break;
case 1:
$ratio = rand() % 100;
// 특기보정 : 반계
if($general['special2'] == 45 && $ratio > 70) {
$oppbatlog[] = "<C>●</><D>매복</>을 <R>역으로</> 당했다!";
$batlog[] = "<C>●</><C>반계</>로 상대의 <D>매복</>을 되돌렸다!";
$opCrew *= 1.4;
} else {
$oppbatlog[] = "<C>●</><D>매복</>을 <C>성공</>했다!";
$batlog[] = "<C>●</><D>매복</>에 당했다!";
$myCrew *= 1.4;
}
break;
case 2:
$ratio = rand() % 100;
// 특기보정 : 반계
if($general['special2'] == 45 && $ratio > 70) {
$oppbatlog[] = "<C>●</><D>반목</>을 <R>역으로</> 당했다!";
$batlog[] = "<C>●</><C>반계</>로 상대의 <D>반목</>을 되돌렸다!";
$opCrew *= 1.6;
} else {
$oppbatlog[] = "<C>●</><D>반목</>을 <C>성공</>했다!";
$batlog[] = "<C>●</><D>반목</>에 당했다!";
$myCrew *= 1.6;
// 특기보정 : 반계
if($oppose['special2'] == 45) { $myCrew *= 2; }
}
break;
case 3:
$ratio = rand() % 100;
// 특기보정 : 반계
if($general['special2'] == 45 && $ratio > 70) {
$oppbatlog[] = "<C>●</><D>화계</>를 <R>역으로</> 당했다!";
$batlog[] = "<C>●</><C>반계</>로 상대의 <D>화계</>을 되돌렸다!";
$opCrew *= 1.8;
} else {
$oppbatlog[] = "<C>●</><D>화계</>를 <C>성공</>했다!";
$batlog[] = "<C>●</><D>화계</>에 당했다!";
$myCrew *= 1.8;
}
break;
case 4:
$ratio = rand() % 100;
// 특기보정 : 반계
if($general['special2'] == 45 && $ratio > 70) {
$oppbatlog[] = "<C>●</><D>혼란</>을 <R>역으로</> 당했다!";
$batlog[] = "<C>●</><C>반계</>로 상대의 <D>혼란</>을 되돌렸다!";
$opCrew *= 2.0;
} else {
$oppbatlog[] = "<C>●</><D>혼란</>을 <C>성공</>했다!";
$batlog[] = "<C>●</><D>혼란</>에 당했다!";
$myCrew *= 2.0;
}
break;
}
} else {
$type = rand() % 5; // 0~4
switch($type) {
case 0:
$oppbatlog[] = "<C>●</><D>위보</>를 <R>실패</>했다!";
$batlog[] = "<C>●</><D>위보</>를 간파했다!";
$myCrew /= 1.1; $opCrew *= 1.1;
break;
case 1:
$oppbatlog[] = "<C>●</><D>매복</>을 <R>실패</>했다!";
$batlog[] = "<C>●</><D>매복</>을 간파했다!";
$myCrew /= 1.2; $opCrew *= 1.2;
break;
case 2:
$oppbatlog[] = "<C>●</><D>반목</>을 <R>실패</>했다!";
$batlog[] = "<C>●</><D>반목</>을 간파했다!";
$myCrew /= 1.3; $opCrew *= 1.3;
break;
case 3:
$oppbatlog[] = "<C>●</><D>화계</>를 <R>실패</>했다!";
$batlog[] = "<C>●</><D>화계</>를 간파했다!";
$myCrew /= 1.4; $opCrew *= 1.4;
break;
case 4:
$oppbatlog[] = "<C>●</><D>혼란</>을 <R>실패</>했다!";
$batlog[] = "<C>●</><D>혼란</>을 간파했다!";
$myCrew /= 1.5; $opCrew *= 1.5;
break;
}
}
}
}
// 특기보정: 돌격
if($oppose['crewtype'] == 43 && $general['special2'] != 60) { // 목우
$r = 0;
$r += $oppose['atmos'] + $oppAtmos + $oppAtmosBonus;
$r += $oppose['train'] + $oppTrain + $oppTrainBonus;
$ratio = rand() % 400; // 최대 50% 저지
if($ratio < $r && $opAvoid == 1) {
$batlog[] = "<C>●</><R>저지</>당했다!</>";
$oppbatlog[] = "<C>●</>상대를 <C>저지</>했다!</>";
$opAvoid = 0;
continue;
}
}
// my 입장 상성
// 보병계열 > 궁병계열
if(intdiv($general['crewtype'], 10) == 0 && intdiv($oppose['crewtype'], 10) == 1) {
$myCrew *= 0.8;
$opCrew *= 1.2;
}
// 궁병계열 > 기병계열
if(intdiv($general['crewtype'], 10) == 1 && intdiv($oppose['crewtype'], 10) == 2) {
$myCrew *= 0.8;
$opCrew *= 1.2;
}
// 기병계열 > 보병계열
if(intdiv($general['crewtype'], 10) == 2 && intdiv($oppose['crewtype'], 10) == 0) {
$myCrew *= 0.8;
$opCrew *= 1.2;
}
// 차병계열
if(intdiv($general['crewtype'], 10) == 4) {
$myCrew *= 1.2;
$opCrew *= 0.8;
}
// op 입장 상성
// 보병계열 > 궁병계열
if(intdiv($oppose['crewtype'], 10) == 0 && intdiv($general['crewtype'], 10) == 1) {
$opCrew *= 0.8;
$myCrew *= 1.2;
}
// 궁병계열 > 기병계열
if(intdiv($oppose['crewtype'], 10) == 1 && intdiv($general['crewtype'], 10) == 2) {
$opCrew *= 0.8;
$myCrew *= 1.2;
}
// 기병계열 > 보병계열
if(intdiv($oppose['crewtype'], 10) == 2 && intdiv($general['crewtype'], 10) == 0) {
$opCrew *= 0.8;
$myCrew *= 1.2;
}
// 차병계열
if(intdiv($oppose['crewtype'], 10) == 4) {
$opCrew *= 1.2;
$myCrew *= 0.8;
}
//군주 공격 보정 10%
if($general['level'] == 12) {
$opCrew = $opCrew * 1.10;
//참모, 장군 공격 보정 5%
} elseif($general['level'] == 11 || $general['level'] == 10 || $general['level'] == 8 || $general['level'] == 6) {
$opCrew = $opCrew * 1.05;
}
//상대장수 관직 보정
//군주 방어 보정 10%
if($oppose['level'] == 12) {
$opCrew = $opCrew * 0.90;
//참모, 모사 방어 보정 5%
} elseif($oppose['level'] == 11 || $oppose['level'] == 9 || $oppose['level'] == 7 || $oppose['level'] == 5) {
$opCrew = $opCrew * 0.95;
} elseif($oppose['level'] == 4 && $oppose['no'] == $city['gen1']) { // 태수 보정
$opCrew = $opCrew * 0.95;
} elseif($oppose['level'] == 3 && $oppose['no'] == $city['gen2']) { // 군사 보정
$opCrew = $opCrew * 0.95;
} elseif($oppose['level'] == 2 && $oppose['no'] == $city['gen3']) { // 시중 보정
$opCrew = $opCrew * 0.95;
}
//레벨 보정
$myCrew = $myCrew * (max(1, 100 - $general['explevel']/3)/100);
$opCrew = $opCrew / (max(1, 100 - $general['explevel']/3)/100);
$myCrew = $myCrew / (max(1, 100 - $oppose['explevel']/3)/100);
$opCrew = $opCrew * (max(1, 100 - $oppose['explevel']/3)/100);
// 특기보정 : 기병, 돌격, 무쌍, 보병, 견고, 척사, 의술(청낭서, 태평청령)
if($general['special2'] == 52) { $opCrew *= 1.20; }
if($general['special2'] == 60) { $opCrew *= 1.10; }
if($general['special2'] == 61) { $opCrew *= 1.10; }
if($general['special2'] == 50) { $myCrew *= 0.90; }
if($general['special2'] == 62) { $myCrew *= 0.90; }
if($general['special2'] == 75) {
if($oppose['crewtype'] != 0 && $oppose['crewtype'] != 10 && $oppose['crewtype'] != 20 &&
$oppose['crewtype'] != 30 && $oppose['crewtype'] != 40 && $oppose['crewtype'] != 41)
{
$opCrew *= 1.1; $myCrew *= 0.9;
}
}
$ratio = rand() % 100; // 0 ~ 99
if(($general['special2'] == 73 || $general['item'] == 23 || $general['item'] == 24) && $ratio > 80 && $myAvoid == 1) {
$batlog[] = "<C>●</><C>치료</>했다!</>";
$myCrew /= 1.5; // 66%만 소모
$myAvoid = 0;
}
// 상대 특기보정 : 기병, 무쌍, 보병, 견고, 척사, 의술(청낭서, 태평청령)
if($oppose['special2'] == 52) { $myCrew *= 1.10; }
if($oppose['special2'] == 61) { $myCrew *= 1.10; }
if($oppose['special2'] == 50) { $opCrew *= 0.80; }
if($oppose['special2'] == 62) { $myCrew *= 1.10; }
if($oppose['special2'] == 75) {
if($general['crewtype'] != 0 && $general['crewtype'] != 10 && $general['crewtype'] != 20 &&
$general['crewtype'] != 30 && $general['crewtype'] != 40 && $general['crewtype'] != 41)
{
$myCrew *= 1.1; $opCrew *= 0.9;
}
}
$ratio = rand() % 100; // 0 ~ 99
if(($oppose['special2'] == 73 || $oppose['item'] == 23 || $oppose['item'] == 24) && $ratio > 80 && $opAvoid == 1) {
$oppbatlog[] = "<C>●</><C>치료</>했다!</>";
$opCrew /= 1.5; // 66%만 소모
$opAvoid = 0;
}
//크리
$rd = rand() % 100; // 0 ~ 99
$ratio = CriticalRatio3($general);
// 특기보정 : 무쌍, 필살
if($general['special2'] == 61) { $ratio += 10; }
if($general['special2'] == 71) { $ratio += 20; }
if($ratio >= $rd && $myAvoid == 1) {
$batlog[] = "<C>●</><C>필살</>공격!</>";
$oppbatlog[] = "<C>●</>상대의 <R>필살</>공격!</>";
$opCrew = CriticalScore2($opCrew);
$myAvoid = 0;
// 특기보정 : 격노
if($oppose['special2'] == 74) {
if(rand() % 100 < 50) {
$batlog[] = "<C>●</>필살 공격에 상대가 <R>격노</>했다!</>";
$oppbatlog[] = "<C>●</>상대의 필살 공격에 <C>격노</>했다!</>";
$myCrew = CriticalScore2($myCrew);
$opAvoid = 0;
}
}
}
//크리
$rd = rand() % 100; // 0 ~ 99
$ratio = CriticalRatio3($oppose);
// 특기보정 : 필살
if($oppose['special2'] == 71) { $ratio += 20; }
if($ratio >= $rd && $opAvoid == 1) {
$oppbatlog[] = "<C>●</><C>필살</>공격!</>";
$batlog[] = "<C>●</>상대의 <R>필살</>공격!</>";
$myCrew = CriticalScore2($myCrew);
$opAvoid = 0;
// 특기보정 : 격노
if($general['special2'] == 74) {
if(rand() % 100 < 33) {
$oppbatlog[] = "<C>●</>필살 공격에 상대가 <R>진노</>했다!</>";
$batlog[] = "<C>●</>상대의 필살 공격에 <C>진노</>했다!</>";
$opCrew = CriticalScore2($opCrew);
$myAvoid = 0;
$warphase++;
} elseif(rand() % 100 < 33) {
$oppbatlog[] = "<C>●</>필살 공격에 상대가 <R>격노</>했다!</>";
$batlog[] = "<C>●</>상대의 필살 공격에 <C>격노</>했다!</>";
$opCrew = CriticalScore2($opCrew);
$myAvoid = 0;
}
}
}
//회피
$ratio = rand() % 100; // 0 ~ 99
$ratio2 = GameUnitConst::byID($general['crewtype'])->avoid; //회피율
$ratio2 = Util::round($ratio2 * $general['train'] / 100); //훈련 반영
//특기보정 : 돌격, 궁병
if($oppose['special2'] == 60) { $ratio2 -= 100; }
if($general['special2'] == 51) { $ratio2 += 20; }
//도구 보정 : 둔갑천서, 태평요술
if($general['item'] == 26 || $general['item'] == 25) { $ratio2 += 20; }
if($ratio < $ratio2 && $myAvoid == 1) {
// 특기보정 : 격노
if($oppose['special2'] == 74 && rand() % 100 < 50) {
$batlog[] = "<C>●</>회피 시도에 상대가 <R>격노</>했다!</>";
$oppbatlog[] = "<C>●</>상대의 회피 시도에 <C>격노</>했다!</>";
$myCrew = CriticalScore2($myCrew);
$opAvoid = 0;
} else {
$batlog[] = "<C>●</><C>회피</>했다!</>";
$oppbatlog[] = "<C>●</>상대가 <R>회피</>했다!</>";
$myCrew /= 5; // 20%만 소모
$myAvoid = 0;
}
}
//회피
$ratio = rand() % 100; // 0 ~ 99
$ratio2 = GameUnitConst::byID($oppose['crewtype'])->avoid; //회피율
$ratio2 = Util::round($ratio2 * $oppose['train'] / 100); //훈련 반영
// 특기보정 : 돌격, 궁병
if($general['special2'] == 60) { $ratio2 -= 100; }
if($oppose['special2'] == 51) { $ratio2 += 20; }
//도구 보정 : 둔갑천서, 태평요술
if($oppose['item'] == 26 || $oppose['item'] == 25) { $ratio2 += 20; }
if($ratio < $ratio2 && $opAvoid == 1) {
// 특기보정 : 격노
if($general['special2'] == 74 && rand() % 100 < 33) {
$oppbatlog[] = "<C>●</>회피 시도에 상대가 <R>진노</>했다!</>";
$batlog[] = "<C>●</>상대의 회피 시도에 <C>진노</>했다!</>";
$opCrew = CriticalScore2($opCrew);
$myAvoid = 0;
$warphase++;
} elseif($general['special2'] == 74 && rand() % 100 < 33) {
$oppbatlog[] = "<C>●</>회피 시도에 상대가 <R>격노</>했다!</>";
$batlog[] = "<C>●</>상대의 회피 시도에 <C>격노</>했다!</>";
$opCrew = CriticalScore2($opCrew);
$myAvoid = 0;
} else {
$oppbatlog[] = "<C>●</><C>회피</>했다!</>";
$batlog[] = "<C>●</>상대가 <R>회피</>했다!</>";
$opCrew /= 5; // 20%만 소모
$opAvoid = 0;
}
}
//랜타추가
$opCrew *= (rand() % 21 + 90)/100; // 90~110%
$myCrew *= (rand() % 21 + 90)/100; // 90~110%
//특기보정 : 위압
if($general['special2'] == 63 && $phase == 1 && $general['crew'] >= 1000 && $general['atmos'] >= 90 && $general['train'] >= 90) {
$batlog[] = "<C>●</>상대에게 <C>위압</>을 줬다!</>";
$oppbatlog[] = "<C>●</>상대에게 <R>위압</>받았다!</>";
$myCrew = 0;
}
//특기보정: 위압
if($oppose['special2'] == 63 && $phase == 1 && $oppose['crew'] >= 1000 && $oppose['atmos'] >= 90 && $oppose['train'] >= 90) {
$batlog[] = "<C>●</>상대에게 <R>위압</>받았다!</>";
$oppbatlog[] = "<C>●</>상대에게 <C>위압</>을 줬다!</>";
$opCrew = 0;
}
$general['crew'] -= Util::round($myCrew);
$oppose['crew'] -= Util::round($opCrew);
$tempMyCrew = $myCrew; $tempOpCrew = $opCrew;
$tempGeneralCrew = $general['crew']; $tempOpposeCrew = $oppose['crew'];
if($general['crew'] <= 0 && $oppose['crew'] <= 0) {
$r1 = $tempGeneralCrew / $tempMyCrew;
$r2 = $tempOpposeCrew / $tempOpCrew;
if($r1 > $r2) {
$offset = Util::round($tempOpposeCrew*$tempMyCrew/$tempOpCrew);
$myCrew += $offset;
$general['crew'] -= $offset;
$opCrew += $tempOpposeCrew;
$oppose['crew'] = 0;
} else {
$offset = Util::round($tempGeneralCrew*$tempOpCrew/$tempMyCrew);
$opCrew += $offset;
$oppose['crew'] -= $offset;
$myCrew += $tempGeneralCrew;
$general['crew'] = 0;
}
} elseif($general['crew'] * $oppose['crew'] <= 0) {
if($oppose['crew'] < 0) {
$offset = Util::round($tempOpposeCrew*$tempMyCrew/$tempOpCrew);
$myCrew += $offset;
$general['crew'] -= $offset;
$opCrew += $tempOpposeCrew;
$oppose['crew'] = 0;
}
if($general['crew'] < 0) {
$offset = Util::round($tempGeneralCrew*$tempOpCrew/$tempMyCrew);
$opCrew += $offset;
$oppose['crew'] -= $offset;
$myCrew += $tempGeneralCrew;
$general['crew'] = 0;
}
}
$exp += $opCrew;
$opexp += $myCrew;
$general['crew'] = Util::round($general['crew']);
$oppose['crew'] = Util::round($oppose['crew']);
$myCrew = Util::round($myCrew);
$opCrew = Util::round($opCrew);
$batlog[] = "<C>●</> $phase : <Y1>【{$general['name']}】</> <C>{$general['crew']} (-$myCrew)</> VS <C>{$oppose['crew']} (-$opCrew)</> <Y1>【{$oppose['name']}】</>";
$oppbatlog[] = "<C>●</> $phase : <Y1>【{$oppose['name']}】</> <C>{$oppose['crew']} (-$opCrew)</> VS <C>{$general['crew']} (-$myCrew)</> <Y1>【{$general['name']}】</>";
$mykillnum += $opCrew; $mydeathnum += $myCrew;
$opkillnum += $myCrew; $opdeathnum += $opCrew;
// 중간 쌀 체크
$myRice = Util::round($exp / 50);
// 성격 보정
$myRice = CharExperience($myRice, $general['personal']);
// 쌀 소모
$myRice = ($myRice * 5 * getCrewtypeRice($general['crewtype'], $nation['tech']));
// 결과 쌀
$myRice = $general['rice'] - $myRice;
// 중간 쌀 체크
$opRice = Util::round($opexp / 50 * 0.8);
// 성격 보정
$opRice = CharExperience($opRice, $oppose['personal']);
// 쌀 소모
$opRice = ($opRice * 5 * getCrewtypeRice($oppose['crewtype'], $destnation['tech']));
// 결과 쌀
$opRice = $oppose['rice'] - $opRice;
if($opRice <= Util::round($oppose['crew']/100)) { break; }
if($myRice <= Util::round($general['crew']/100)) { break; }
if($oppose['crew'] <= 0) { break; }
if($general['crew'] <= 0) { break; }
}
$render_attacker = [
'crewtype' => mb_substr(GameUnitConst::byId($general['crewtype'])->name, 0, 2),
'name'=> $general['name'],
'remain_crew' => $general['crew'],
'killed_crew' => -$mydeathnum
];
$render_defender = [
'crewtype' => mb_substr(GameUnitConst::byId($oppose['crewtype'])->name, 0, 2),
'name'=> $oppose['name'],
'remain_crew' => $oppose['crew'],
'killed_crew' => -$opdeathnum
];
$res = str_replace(["\r\n", "\r", "\n"], '', $templates->render('small_war_log',[
'year'=>$year,
'month'=>$month,
'war_type'=>'attack',
'war_type_str'=>'→',
'me' => $render_attacker,
'you' => $render_defender,
]));
$oppres = str_replace(["\r\n", "\r", "\n"], '', $templates->render('small_war_log',[
'year'=>$year,
'month'=>$month,
'war_type'=>'defense',
'war_type_str'=>'←',
'me' => $render_defender,
'you' => $render_attacker,
]));
$log[] = $res;
$batlog[] = $res;
$batres[] = $res;
$opplog[] = $oppres;
$oppbatlog[] = $oppres;
$oppbatres[] = $oppres;
$deadAmount['att'] = $deadAmount['att'] + $mydeathnum;
$deadAmount['def'] = $deadAmount['def'] + $opdeathnum;
// 상대장수 부상
$ratio = rand() % 100;
if($ratio >= 95) {
$opplog[] = "<C>●</>전투중 <R>부상</>당했다!";
$oppose['injury'] += rand() % 71 + 10; // 10 ~ 80
if($oppose['injury'] > 80) { $oppose['injury'] = 80; }
}
// 병사수 변경
$query = "update general set injury='{$oppose['injury']}',crew='{$oppose['crew']}',killcrew=killcrew+'$opkillnum',deathcrew=deathcrew+'$opdeathnum' where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 숙련도 증가
addGenDex($oppose['no'], $general['atmos'], $general['train'], $oppose['crewtype'], $opkillnum * 0.9);
addGenDex($oppose['no'], $general['atmos'], $general['train'], $general['crewtype'], $opdeathnum * 0.9);
// 죽은수 기술로 누적
$num = Util::round($mydeathnum * 0.01);
// 국가보정
if($nation['type'] == 3 || $nation['type'] == 13) { $num *= 1.1; }
if($nation['type'] == 5 || $nation['type'] == 6 || $nation['type'] == 7 || $nation['type'] == 8 || $nation['type'] == 12) { $num *= 0.9; }
// 부드러운 기술 제한
if(TechLimit($admin['startyear'], $year, $nation['tech'])) { $num = intdiv($num, 4); }
$query = "update nation set totaltech=totaltech+'$num',tech=totaltech/'$gencount' where nation='{$nation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 장수 부상
$ratio = rand() % 100;
if($ratio >= 95) {
$log[] = "<C>●</>전투중 <R>부상</>당했다!";
$general['injury'] += rand() % 71 + 10; // 10 ~ 80
if($general['injury'] > 80) { $general['injury'] = 80; }
}
// 병사수 변경
$query = "update general set injury='{$general['injury']}',crew='{$general['crew']}',killcrew=killcrew+'$mykillnum',deathcrew=deathcrew+'$mydeathnum' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 숙련도 증가
addGenDex($general['no'], $general['atmos'], $general['train'], $general['crewtype'], $mykillnum);
addGenDex($general['no'], $general['atmos'], $general['train'], $oppose['crewtype'], $mydeathnum);
// 죽은수 기술로 누적
$num = Util::round($opdeathnum * 0.01);
// 국가보정
if($destnation['type'] == 3 || $destnation['type'] == 13) { $num *= 1.1; }
if($destnation['type'] == 5 || $destnation['type'] == 6 || $destnation['type'] == 7 || $destnation['type'] == 8 || $destnation['type'] == 12) { $num *= 0.9; }
// 부드러운 기술 제한
if(TechLimit($admin['startyear'], $year, $destnation['tech'])) { $num = intdiv($num, 4); }
$query = "update nation set totaltech=totaltech+'$num',tech=totaltech/'$destgencount' where nation='{$destnation['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
//양국 평균 기술가격
//$techRatio = (getTechCost($nation['tech']) + getTechCost($destnation['tech'])) / 2;
$techRatio = 1.0;
// 죽은수 도시 재정으로 누적 60%
$num = Util::round(($mykillnum+$mydeathnum) * 0.6 * $techRatio);
// 국가보정
if($destnation['type'] == 1) { $num *= 1.1; }
if($destnation['type'] == 9 || $destnation['type'] == 10) { $num *= 0.9; }
$query = "update city set dead=dead+'$num' where city='{$city['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 죽은수 도시 재정으로 누적 40%
$num = Util::round(($mykillnum+$mydeathnum) * 0.4 * $techRatio);
// 국가보정
if($nation['type'] == 1) { $num *= 1.1; }
if($nation['type'] == 9 || $nation['type'] == 10) { $num *= 0.9; }
$query = "update city set dead=dead+'$num' where city='{$general['city']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 상대 병사 소진이나 쌀 소진시 다음 장수
if($oppose['crew'] <= 0 || ($opRice <= Util::round($oppose['crew']/100) && $general['crew'] > 0)) {
if($opRice <= Util::round($oppose['crew']/100)) {
$josaYi = JosaUtil::pick(GameUnitConst::byId($oppose['crewtype'])->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$oppose['name']}</>의 ".GameUnitConst::byId($oppose['crewtype'])->name."{$josaYi} 패퇴했습니다.";
$log[] = "<C>●</><Y>{$oppose['name']}</>의 ".GameUnitConst::byId($oppose['crewtype'])->name."{$josaYi} 패퇴했습니다.";
$opplog[] = "<C>●</>군량 부족으로 패퇴합니다.";
} else {
$josaYi = JosaUtil::pick(GameUnitConst::byId($oppose['crewtype'])->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$oppose['name']}</>의 ".GameUnitConst::byId($oppose['crewtype'])->name."{$josaYi} 전멸했습니다.";
$log[] = "<C>●</><Y>{$oppose['name']}</>의 ".GameUnitConst::byId($oppose['crewtype'])->name."{$josaYi} 전멸했습니다.";
$opplog[] = "<C>●</>전멸했습니다.";
}
$opposecount--;
$general['atmos'] *= 1.1; //사기 증가
if($general['atmos'] > GameConst::$maxAtmosByWar) { $general['atmos'] = GameConst::$maxAtmosByWar; }
$query = "update general set atmos='{$general['atmos']}',killnum=killnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$exp2++;
// 상대장수 경험 등등 증가
$opexp = Util::round($opexp / 50 * 0.8);
// 성격 보정
$opexp = CharExperience($opexp, $oppose['personal']);
// 쌀 소모
$oppose['rice'] -= ($opexp * 5 * getCrewtypeRice($oppose['crewtype'], $destnation['tech']));
if($oppose['rice'] < 0) { $oppose['rice'] = 0; }
$query = "update general set deathnum=deathnum+1,rice='{$oppose['rice']}',experience=experience+'$opexp',dedication=dedication+'$opexp' where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$opexp = 0;
pushGenLog($oppose, $opplog);
pushBatLog($oppose, $oppbatlog);
pushBatRes($oppose, $oppbatres);
$oppose = null;
$opplog = [];
$oppbatlog = [];
$oppbatres = [];
// 공격 장수 병사 소진이나 쌀 소진시 실패 처리
} elseif($general['crew'] <= 0 || $myRice <= Util::round($general['crew']/100)) {
if($myRice <= Util::round($general['crew']/100)) {
$josaYi = JosaUtil::pick(GameUnitConst::byId($general['crewtype'])->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>의 ".GameUnitConst::byId($general['crewtype'])->name."{$josaYi} 퇴각했습니다.";
$log[] = "<C>●</>군량 부족으로 퇴각합니다.";
$opplog[] = "<C>●</><Y>{$general['name']}</>의 ".GameUnitConst::byId($general['crewtype'])->name."{$josaYi} 퇴각했습니다.";
} else {
$josaYi = JosaUtil::pick(GameUnitConst::byId($general['crewtype'])->name, '이');
$alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>의 ".GameUnitConst::byId($general['crewtype'])->name."{$josaYi} 퇴각했습니다.";
$log[] = "<C>●</>퇴각했습니다.";
$opplog[] = "<C>●</><Y>{$general['name']}</>의 ".GameUnitConst::byId($general['crewtype'])->name."{$josaYi} 퇴각했습니다.";
}
// 경험치 상승
if(intdiv($oppose['crewtype'], 10) == 3) { // 귀병
$oppose['intel2']++;
} elseif(intdiv($oppose['crewtype'], 10) == 4) { // 차병
$oppose['leader2']++;
} else {
$oppose['power2']++;
}
$oppose['atmos'] *= 1.1; //사기 증가
if($oppose['atmos'] > GameConst::$maxAtmosByWar) { $oppose['atmos'] = GameConst::$maxAtmosByWar; }
// 상대장수 경험 등등 증가
$opexp = Util::round($opexp / 50 * 0.8);
// 성격 보정
$opexp = CharExperience($opexp, $oppose['personal']);
// 쌀 소모
$oppose['rice'] -= ($opexp * 5 * getCrewtypeRice($oppose['crewtype'], $destnation['tech']));
if($oppose['rice'] < 0) { $oppose['rice'] = 0; }
$query = "update general set rice='{$oppose['rice']}',leader2='{$oppose['leader2']}',power2='{$oppose['power2']}',intel2='{$oppose['intel2']}',atmos='{$oppose['atmos']}',experience=experience+'$opexp',dedication=dedication+'$opexp',killnum=killnum+1 where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$query = "update general set deathnum=deathnum+1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$opexp = 0;
$opplog = checkAbility($oppose, $opplog);
pushGenLog($oppose, $opplog);
pushBatLog($oppose, $oppbatlog);
pushBatRes($oppose, $oppbatres);
$opplog = [];
$oppbatlog = [];
$oppbatres = [];
// $josaYi = JosaUtil::pick($general['name'], '이');
// $alllog[] = "<C>●</>{$month}월:<Y>{$general['name']}</>{$josaYi} }<G>{$city['name']}</> 공략에 실패했습니다. <1>$date</>";
// $log[] = "<C>●</> <G>{$city['name']}</> 공략에 실패했습니다. <1>$date</>";
break;
} else {
// 무승부일때 로그 남김
pushGenLog($oppose, $opplog);
pushBatLog($oppose, $oppbatlog);
pushBatRes($oppose, $oppbatres);
$opplog = [];
$oppbatlog = [];
$oppbatres = [];
}
usort($defenderList, function($lhs, $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
});
$iterDefender = new \ArrayIterator($defenderList);
$iterDefender->rewind();
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, $db) {
if($prevDefender !== null){
$prevDefender->applyDB($db);
}
if(!$reqNext){
return null;
}
if(!$iterDefender->valid()){
return null;
}
$retVal = new WarUnitGeneral($iterDefender->current(), $rawDefenderCity, $rawDefenderNation, false, $year, $month);
$iterDefender->next();
return $retVal;
};
$conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear);
$attacker->applyDB($db);
//NOTE: $rawAttackerNation과 $rawDefenderNation은 전투중에 '바뀌지 않음'을 전제로 하고 있다. (현재 구현도 그렇게 되어있음)
$rawDefenderCity = $city->getRaw();
$updateAttackerNation = [];
$updateDefenderNation = [];
if($city->getVar('supply')){
if($city->getPhase() > 0){
$rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice;
$rice *= getTechCost($rawDefenderNation['tech']);
$rice *= $cityRate / 100 - 0.2;
Util::setRound($rice);
$updateDefenderNation['rice'] = max(0, $rawDefenderNation['rice'] - $rice);
}
else if($conquerCity){
$updateDefenderNation['rice'] = $rawDefenderNation['rice'] + 500;
}
}
if(isset($oppose)){
//마지막 페이즈에 장수가 전멸하지 않은 경우. 쌀 소모 후속 처리
// 상대장수 경험 등등 증가(페이즈 초과시)
$opexp = Util::round($opexp / 50 * 0.8);
// 성격 보정
$opexp = CharExperience($opexp, $oppose['personal']);
// 쌀 소모
$oppose['rice'] -= ($opexp * 5 * getCrewtypeRice($oppose['crewtype'], $destnation['tech']));
if($oppose['rice'] < 0) { $oppose['rice'] = 0; }
$query = "update general set rice='{$oppose['rice']}',experience=experience+'$opexp',dedication=dedication+'$opexp' where no='{$oppose['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
}
// 경험치 상승
if(intdiv($general['crewtype'], 10) == 3) { // 귀병
$general['intel2'] += $exp2;
} elseif(intdiv($general['crewtype'], 10) == 4) { // 차병
$general['leader2'] += $exp2;
} else {
$general['power2'] += $exp2;
}
$query = "update general set leader2='{$general['leader2']}',power2='{$general['power2']}',intel2='{$general['intel2']}' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 공헌, 명성 상승
$exp = Util::round($exp / 50);
// 성격 보정
$exp = CharExperience($exp, $general['personal']);
// 쌀 소모
$general['rice'] -= ($exp * 5 * getCrewtypeRice($general['crewtype'], $nation['tech']));
if($general['rice'] < 0) { $general['rice'] = 0; }
$query = "update general set rice='{$general['rice']}',dedication=dedication+'$exp',experience=experience+'$exp' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$log = checkAbility($general, $log);
pushGenLog($general, $log);
pushBatLog($general, $batlog);
pushBatRes($general, $batres);
pushGeneralPublicRecord($alllog, $year, $month);
pushWorldHistory($history);
return $deadAmount;
}
function CriticalRatio3($general) {
// 무장 무력 : 65 5%, 70 10%, 75 15%, 80 20%
// 지장 지력 : 65 5%, 70 8%, 75 10%, 80 13%
//충차장 통솔: 65 5%, 70 8%, 75 10%, 80 13%
$crewtype = intdiv($general['crewtype'], 10);
if($crewtype == 3){ //지장
$mainstat = getGeneralIntel($general, false, true, true, false);
}
else if($crewtype == 4){ //병기
$mainstat = getGeneralLeadership($general, false, true, true, false);
}
else{ //무장
$mainstat = getGeneralPower($general, false, true, true, false);
}
$ratio = max($mainstat - 65, 0);
if ($crewtype >= 3) {
$ratio *= 0.4;
}
else{
$ratio *= 0.5;
}
$ratio = round($ratio);
$ratio += 5;
if($ratio > 50) $ratio = 50;
return $ratio;
}
function CriticalScore2($score) {
$score = Util::round($score * (rand()%8 + 13)/10); // 1.3~2.0
return $score;
}
//0 0 : 100 100 이면 최고 무한대 차이
//30 30 : 100 100 이면 최고 3.3배 차이
//60 60 : 100 100 이면 최고 1.6배 차이
function getCrew($crew, $youatmos, $mytrain) {
$ratio = $youatmos / $mytrain;
$crew = $crew * $ratio;
return $crew;
}
function getCrewtypeRice($crewtype, $tech) {
if(!$crewtype) { $crewtype = 0; }
$cost = GameUnitConst::byID($crewtype)->rice / 10;
return $cost * getTechCost($tech);
}
//////////////////////////////////////////////////////////////
// 표준 공 / 수 반환 수치는 약 0이 되게 (100~550)
//////////////////////////////////////////////////////////////
function getAtt($general, $tech, $lbonus) {
$att = GameUnitConst::byID($general['crewtype'])->attack + getTechAbil($tech);
$general['lbonus'] = $lbonus;
if(intdiv($general['crewtype'], 10) == 3) { // 귀병 지100%
$ratio = getGeneralIntel($general, true, true, true)*2 - 40;
} elseif(intdiv($general['crewtype'], 10) == 4) { // 차병 통100%
$ratio = getGeneralLeadership($general, true, true, true)*2 - 40;
} else {
$ratio = getGeneralPower($general, true, true, true)*2 - 40; //10일때 -20, 70일때 100, 100일때 160
}
if($ratio < 10) { $ratio = 10; }
if($ratio > 100) { $ratio = 50 + $ratio/2; } // 100보다 큰 경우는 상승률 1/2
$att = $att * $ratio / 100;
return $att;
}
function getDef($general, $tech) {
$def = GameUnitConst::byID($general['crewtype'])->defence + getTechAbil($tech);
$crew = ($general['crew'] / (7000 / 30)) + 70; // 5000명일때 91점 7000명일때 100점 10000명일때 113점
$def = $def * $crew / 100;
return $def;
}
function getCityAtt($city) {
$att = ($city['def']*0.1 + $city['wall']*0.9) / 500 + 200; //50000일때 300점 100000일때 400점
return $att;
}
function getCityDef($city) {
$def = ($city['def']*0.1 + $city['wall']*0.9) / 500 + 200;
return $def;
}
function getRate($admin, $type, $dtype) {
$t = "{$dtype}{$type}";
return $admin[$t];
}
function addConflict($city, $nationID, $mykillnum) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$nationlist = [];
$killnum = [0];
list($year, $month) = $gameStor->getValuesAsArray(['year', 'month']);
$conflict = Json::decode($city['conflict']);
if(!$conflict || $city['def'] == 0){ // 선타, 막타 보너스
$mykillnum *= 1.05;
}
if (!$conflict) {
$conflict[$nationID] = $mykillnum;
}
else if(key_exists($nationID, $conflict)){
$conflict[$nationID] += $mykillnum;
arsort($conflict);
}
else{
$conflict[$nationID] = $mykillnum;
arsort($conflict);
$nation = getNationStaticInfo($nationID);
$josaYi = JosaUtil::pick($nation['name'], '이');
pushWorldHistory(["<C>●</>{$year}{$month}월:<M><b>【분쟁】</b></><D><b>{$nation['name']}</b></>{$josaYi} <G><b>{$city['name']}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다."]);
}
$rawConflict = Json::encode($conflict);
$city['conflict'] = $rawConflict;
$totalDead = $attacker->getKilled() + $attacker->getDead();
$db->update('city', [
'conflict'=>$rawConflict
], 'city=%i',$city['city']);
'dead' => $db->sqleval('dead + %i', $totalDead * 0.4)
], 'city=%i', $rawAttackerCity['city']);
return $city;
$db->update('city', [
'dead' => $db->sqleval('dead + %i', $totalDead * 0.6)
], 'city=%i', $rawDefenderCity['city']);
$attackerIncTech = $attacker->getDead() * 0.01 * getNationTechMultiplier($rawAttackerNation['type']);
$defenderIncTech = $attacker->getKilled() * 0.01 * getNationTechMultiplier($rawDefenderNation['type']);
if(TechLimit($startYear, $year, $rawAttackerNation['tech'])){
$attackerIncTech /= 4;
}
if(TechLimit($startYear, $year, $rawDefenderNation['tech'])){
$defenderIncTech /= 4;
}
$attackerTotalTech = $rawAttackerNation['totaltech'] + $attackerIncTech;
$defenderTotalTech = $rawDefenderNation['totaltech'] + $defenderIncTech;
$updateAttackerNation['totaltech'] = Util::round($attackerTotalTech);
$updateDefenderNation['totaltech'] = Util::round($defenderTotalTech);
$updateAttackerNation['tech'] = Util::round($attackerTotalTech / max(GameConst::$initialNationGenLimit, $rawAttackerNation['gennum']));
$updateDefenderNation['tech'] = Util::round($defenderTotalTech / max(GameConst::$initialNationGenLimit, $rawDefenderNation['gennum']));
$db->update('nation', $updateAttackerNation, 'nation=%i', $attackerNationID);
$db->update('nation', $updateDefenderNation, 'nation=%i', $defenderNationID);
$db->update('diplomacy', [
'dead'=>$db->sqleval('dead + %i', $attacker->getDead() * getTechCost($rawAttackerNation['tech']))
], 'me = %i and you = %i', $attackerNationID, $defenderNationID);
$db->update('diplomacy', [
'dead'=>$db->sqleval('dead + %i', $attacker->getKilled() * getTechCost($rawDefenderNation['tech']))
], 'me = %i and you = %i', $defenderNationID, $attackerNationID);
if(!$conquerCity){
return;
}
//XXX: 새 도시점령 코드 작성하기 전까지 유지
$rawAttackerCity = $db->queryFirstRow('SELECT * FROM city WHERE city = %i', $rawAttacker['city']);
$rawAttackerNation = $db->queryFirstRow('SELECT nation,`level`,`name`,capital,totaltech,gennum,tech,`type`,gold,rice FROM nation WHERE nation = %i', $attackerNationID);
if($defenderNationID !== 0){
$rawDefenderNation = $db->queryFirstRow('SELECT nation,`level`,`name`,capital,totaltech,gennum,tech,`type`,gold,rice FROM nation WHERE nation = %i', $defenderNationID);
}
ConquerCity([
'startyear'=>$startYear,
'year'=>$year,
'month'=>$month,
'city_rate'=>$cityRate
], $attacker->getRaw(), $city->getRaw(), $rawAttackerNation, $rawDefenderNation);
}
function extractBattleOrder($general){
return (
$general['leader'] +
$general['power'] +
$general['intel'] +
$general['weap'] +
$general['horse'] +
$general['book'] +
$general['crew'] / 100
);
}
function processWar_NG(
WarUnitGeneral $attacker,
callable $getNextDefender,
WarUnitCity $city,
int $relYear
):bool{
$templates = new \League\Plates\Engine(__dir__.'/templates');
$logger = $attacker->getLogger();
$attacker->useBattleInitItem();
$date = substr($attacker->getVar('turntime'),11,5);
$attackerNationUpdate = [];
$defenderNationUpdate = [];
$defender = ($getNextDefender)(null, true);
$conquerCity = false;
$josaRo = JosaUtil::pick($city->getName(), '로');
$josaYi = JosaUtil::pick($attacker->getName(), '이');
$logger->pushGlobalActionLog("<D><b>{$attacker->getNationVar('name')}</b></>의 <Y>{$attacker->getName()}</>{$josaYi} <G><b>{$city->getName()}</b></>{$josaRo} 진격합니다.");
$logger->pushGeneralActionLog("<G><b>{$city->getName()}</b></>{$josaRo} <M>진격</>합니다. <1>$date</>");
for($currPhase = 0; $currPhase < $attacker->getMaxPhase(); $currPhase+=1){
if($defender === null){
$defender = $city;
if($city->getNationVar('rice') <= 0 && $city->getVar('supply')){
//병량 패퇴
$attacker->setOppose($defender);
$defender->setOppose($attacker);
$attacker->addTrain(1);
$attacker->addWin();
$defender->addLose();
$defender->heavyDecreseWealth();
$logger->pushGlobalActionLog("병량 부족으로 <G><b>{$defender->getName()}</b></>의 수비병들이 <R>패퇴</>합니다.");
$josaUl = JosaUtil::pick($defender->getName(), '을');
$josaYi = JosaUtil::pick($defender->getNationVar('name'), '이');
$logger->pushGlobalHistoryLog("<M><b>【패퇴】</b></><D><b>{$defender->getNationVar('name')}</b></>{$josaYi} 병량 부족으로 <G><b>{$defender->getName()}</b></>{$josaUl} 뺏기고 말았습니다.");
$conquerCity = true;
break;
}
}
if($defender->getPhase() == 0){
$defender->setPrePhase($currPhase);
$attacker->addTrain(1);
$defender->addTrain(1);
if($defender instanceof WarUnitGeneral){
$josaWa = JosaUtil::pick($attacker->getCrewTypeName(), '와');
$josaYi = JosaUtil::pick($defender->getCrewTypeName(), '이');
$logger->pushGlobalActionLog("<Y>{$attacker->getName()}</>의 {$attacker->getCrewTypeName()}{$josaWa} <Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 대결합니다.");
$josaRo = JosaUtil::pick($attacker->getCrewTypeName(), '로');
$josaUl = JosaUtil::pick($defender->getCrewTypeName(), '을');
$attacker->getLogger()->pushGeneralActionLog("{$attacker->getCrewTypeName()}{$josaRo} <Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaUl} <M>공격</>합니다.");
$josaRo = JosaUtil::pick($defender->getCrewTypeName(), '로');
$josaUl = JosaUtil::pick($attacker->getCrewTypeName(), '을');
$defender->getLogger()->pushGeneralActionLog("{$defender->getCrewTypeName()}{$josaRo} <Y>{$attacker->getName()}</>의 {$attacker->getCrewTypeName()}{$josaUl} <M>수비</>합니다.");
}
else{
$josaYi = JosaUtil::pick($attacker->getName(), '이');
$josaRo = JosaUtil::pick($attacker->getCrewTypeName(), '로');
$logger->pushGlobalActionLog("<Y>{$attacker->getName()}</>{$josaYi} {$attacker->getCrewTypeName()}{$josaRo} 성벽을 공격합니다.");
$logger->pushGeneralActionLog("<C>●</>{$attacker->getCrewTypeName()}{$josaRo} 성벽을 <M>공격</>합니다.", ActionLogger::PLAIN);
}
$defender->useBattleInitItem();
$attacker->setOppose($defender);
$defender->setOppose($attacker);
$attacker->checkBattleBeginSkill();
$defender->checkBattleBeginSkill();
$attacker->checkBattleBeginItem();
$defender->checkBattleBeginItem();
$attacker->applyBattleBeginSkillAndItem();
$defender->applyBattleBeginSkillAndItem();
}
$attacker->beginPhase();
$defender->beginPhase();
$attacker->checkPreActiveSkill();
$defender->checkPreActiveSkill();
$attacker->checkActiveSkill();
$defender->checkActiveSkill();
//NOTE: 마법은 checkActiveSkill, checkPostActiveSkill 내에서 반영
$attacker->checkPostActiveSkill();
$defender->checkPostActiveSkill();
//NOTE: 반계류 등의 스킬을 post에서 반영
$activeSkillIterator = new \AppendIterator();
$activeSkillIterator->append($attacker->applyActiveSkill());
$activeSkillIterator->append($defender->applyActiveSkill());
foreach($activeSkillIterator as $b){
//doNothing
}
$deadDefender = $attacker->calcDamage();
$deadAttacker = $defender->calcDamage();
$attackerHP = $attacker->getHP();
$defenderHP = $defender->getHP();
if($deadAttacker > $attackerHP || $deadDefender > $defenderHP){
$deadAttackerRatio = $deadAttacker / max(1, $attackerHP);
$deadDefenderRatio = $deadDefender / max(1, $defenderHP);
if($deadDefenderRatio > $deadAttackerRatio){
//수비자가 더 병력 부족
$deadAttacker /= $deadDefenderRatio;
$deadDefender = $defenderHP;
}
else{
//공격자가 더 병력 부족
$deadDefender /= $deadAttackerRatio;
$deadAttacker = $attackerHP;
}
}
$deadAttacker = min(ceil($deadAttacker), $attackerHP);
$deadDefender = min(ceil($deadDefender), $defenderHP);
$attacker->decreaseHP($deadAttacker);
$defender->decreaseHP($deadDefender);
$attacker->increaseKilled($deadDefender);
$defender->increaseKilled($deadAttacker);
$phaseNickname = $currPhase + 1;
if($deadAttacker > 0 || $deadDefender > 0){
$attacker->getLogger()->pushGeneralBattleDetailLog(
"$phaseNickname : <Y1>【{$attacker->getName()}】</> <C>{$attacker->getHP()} (-$deadAttacker)</> VS <C>{$defender->getHP()} (-$deadDefender)</> <Y1>【{$defender->getName()}】</>"
);
$defender->getLogger()->pushGeneralBattleDetailLog(
"$phaseNickname : <Y1>【{$defender->getName()}】</> <C>{$defender->getHP()} (-$deadDefender)</> VS <C>{$attacker->getHP()} (-$deadAttacker)</> <Y1>【{$attacker->getName()}】</>"
);
}
$attacker->addPhase();
$defender->addPhase();
if(!$attacker->continueWar($noRice)){
$attacker->logBattleResult();
$defender->logBattleResult();
$attacker->addLose();
$defender->addWin();
$attacker->tryWound();
$defender->tryWound();
$josaYi = JosaUtil::pick($attacker->getCrewTypeName(), '이');
$logger->pushGlobalActionLog("<Y>{$attacker->getName()}</>의 {$attacker->getCrewTypeName()}{$josaYi} 퇴각했습니다.");
if($noRice){
$attacker->getLogger()->pushGeneralActionLog("군량 부족으로 퇴각합니다.", ActionLogger::PLAIN);
}
else{
$attacker->getLogger()->pushGeneralActionLog("퇴각했습니다.", ActionLogger::PLAIN);
}
$defender->getLogger()->pushGeneralActionLog("<Y>{$attacker->getName()}</>의 {$attacker->getCrewTypeName()}{$josaYi} 퇴각했습니다.", ActionLogger::PLAIN);
break;
}
if(!$defender->continueWar($noRice)){
$attacker->logBattleResult();
$defender->logBattleResult();
$attacker->addWin();
$defender->addLose();
$attacker->tryWound();
$defender->tryWound();
if($defender === $city){
$attacker->addLevelExp(1000);
$conquerCity = true;
break;
}
$josaYi = JosaUtil::pick($defender->getCrewTypeName(), '이');
if($noRice){
$logger->pushGlobalActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.");
$attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 패퇴했습니다.", ActionLogger::PLAIN);
$defender->getLogger()->pushGeneralActionLog("군량 부족으로 패퇴합니다.", ActionLogger::PLAIN);
}
else{
$logger->pushGlobalActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 전멸했습니다.");
$attacker->getLogger()->pushGeneralActionLog("<Y>{$defender->getName()}</>의 {$defender->getCrewTypeName()}{$josaYi} 전멸했습니다.", ActionLogger::PLAIN);
$defender->getLogger()->pushGeneralActionLog("전멸했습니다.", ActionLogger::PLAIN);
}
if($currPhase + 1 == $attacker->getMaxPhase()){
break;
}
$defender->finishBattle();
$defender = ($getNextDefender)($defender, true);
if($defender !== null && !($defender instanceof WarUnitGeneral)){
throw new \RuntimeException('다음 수비자를 받아오는데 실패');
}
}
}
$attacker->finishBattle();
$defender->finishBattle();
if($currPhase == $attacker->getMaxPhase()){
//마지막 페이즈의 전투 마무리
$attacker->tryWound();
$defender->tryWound();
$attacker->logBattleResult();
$defender->logBattleResult();
}
if($defender instanceof WarUnitCity){
$newConflict = $defender->addConflict();
if($newConflict){
$nationName = $attacker->getNationVar('name');
$josaYi = JosaUtil::pick($nationName, '이');
$logger->pushGlobalHistoryLog("<M><b>【분쟁】</b></><D><b>{$nationName}</b></>{$josaYi} <G><b>{$defender->getName()}</b></> 공략에 가담하여 분쟁이 발생하고 있습니다.");
}
}
($getNextDefender)($defender, false);
return $conquerCity;
}
function DeleteConflict($nation) {
@@ -1777,30 +472,20 @@ function ConquerCity($admin, $general, $city, $nation, $destnation) {
pushNationHistory($nation, "<C>●</>{$year}{$month}월:<Y>{$general['name']}</>{$josaYiGen} {$destnationName} <G><b>{$city['name']}</b></>{$josaUl} <S>점령</>");
pushNationHistory($destnation, "<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 <Y>{$general['name']}</>에 의해 <G><b>{$city['name']}</b></>{$josaYiCity} <span class='ev_highlight'>함락</span>");
$query = "select city from city where nation='{$city['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$citycount = MYDB_num_rows($result);
$citycount = $db->queryFirstField('SELECT count(city) FROM city WHERE nation = %i', $city['nation']);
// 국가 멸망시
//TODO: 국가 멸망 코드를 별도로 작성
if($citycount == 1 && $city['nation'] != 0) {
$query = "select nation,name,gold,rice from nation where nation='{$city['nation']}'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$losenation = MYDB_fetch_array($result);
$losenation = $destnation;
$josaYi = JosaUtil::pick($losenation['name'], '이');
$josaUl = JosaUtil::pick($losenation['name'], '을');
$history[] = "<C>●</>{$year}{$month}월:<R><b>【멸망】</b></><D><b>{$losenation['name']}</b></>{$josaYi} 멸망하였습니다.";
pushNationHistory($nation, "<C>●</>{$year}{$month}월:<D><b>{$losenation['name']}</b></>{$josaUl} 정복");
$query = "select no, nation from general where nation='{$general['nation']}' and level='12'";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$ruler = MYDB_fetch_array($result);
//다굴치는 나라들 전방설정을 위해 미리 얻어옴
$query = "select you from diplomacy where me='{$losenation['nation']}' and state<2";
$dipResult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$dipCount = MYDB_num_rows($dipResult);
$dipNations = $db->queryFirstColumn('SELECT you FROM diplomacy WHERE me = %i', $losenation['nation']);
$loseGeneralGold = 0;
$loseGeneralRice = 0;
@@ -1836,11 +521,7 @@ function ConquerCity($admin, $general, $city, $nation, $destnation) {
$loseGeneralRice += $loseRice;
//모두 등용장 발부
if($nation['name'] == "강족" || $nation['name'] == "저족" || $nation['name'] == "흉노족"
|| $nation['name'] == "남만족" || $nation['name'] == "산월족" || $nation['name'] == "오환족"
|| $nation['name'] == "왜족") {
//등용장 미발부
} elseif(Util::randBool(0.5)) {
if(Util::randBool(0.5)) {
$msg = ScoutMessage::buildScoutMessage($general['no'], $gen['no']);
if($msg){
$msg->send(true);
@@ -1848,7 +529,7 @@ function ConquerCity($admin, $general, $city, $nation, $destnation) {
}
//NPC인 경우 10% 확률로 임관(엔장, 인재, 의병)
if($gen['npc'] >= 2 && $gen['npc'] <= 4 && rand() % 100 < 10) {
if($gen['npc'] >= 2 && $gen['npc'] <= 8 && rand() % 100 < 10) {
$commissionCommand = EncodeCommand(0, 0, $nation['nation'], 25); //임관
$query = "update general set turn0='$commissionCommand' where no={$gen['no']}";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
@@ -1910,10 +591,9 @@ function ConquerCity($admin, $general, $city, $nation, $destnation) {
$query = "delete from nation where nation='{$city['nation']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
// 아까 얻어온 다굴국들 전방설정
for($i=0; $i < $dipCount; $i++) {
$dip = MYDB_fetch_array($dipResult);
foreach($dipNations as $dip){
//전방설정
SetNationFront($dip['you']);
SetNationFront($dip);
}
// 멸망이 아니면
} else {
+116 -392
View File
@@ -5,10 +5,13 @@ include "lib.php";
include "func.php";
//로그인 검사
$commandtype = Util::getReq('commandtype', 'int', 0);
$turn = Util::getReq('turn', 'array_int', [0]);
$commandtype = Util::getReq('commandtype', 'int');
$turn = Util::getReq('turn', 'array_int');
extractMissingPostToGlobals();
if(!$turn || $commandtype === null){
header('location:commandlist.php');
die();
}
$session = Session::requireGameLogin()->setReadOnly();
@@ -49,8 +52,8 @@ switch($commandtype) {
case 8: command_Single($turn, 8); break; //치안 강화
case 9: command_Single($turn, 9); break; //자금 조달
case 11: command_11( $turn, 11); break; //징병
case 12: command_12( $turn, 12); break; //모병
case 11: command_11( $turn, 11, false); break; //징병
case 12: command_11( $turn, 12, true); break; //모병
case 13: command_Single($turn, 13); break; //훈련
case 14: command_Single($turn, 14); break; //사기진작
//case 15: command_Single($turn, 0); break; //전투태세
@@ -125,11 +128,14 @@ function starter($name, $type=0) {
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/base_map.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('js/map.js')?>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
$(function(){
var $target = $("form[name=form1] select[name=double]");
console.log($target);
@@ -137,6 +143,7 @@ $(function(){
isDetailMap:false,
clickableAll:true,
neutralView:true,
useCachedMap:true,
selectCallback:function(city){
$target.val(city.id);
return false;
@@ -144,7 +151,7 @@ $(function(){
});
});
</script>
<?=WebUtil::printCSS('css/normalize.css')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/main.css')?>
@@ -192,416 +199,133 @@ function command_99($turn) {
header('location:b_chiefcenter.php');
}
function command_11($turn, $command) {
function command_11($turn, $command, bool $is모병 = false) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
$userID = Session::getUserID();
starter("징병");
$me = $db->queryFirstRow(
'SELECT no,nation,level,personal,special2,level,city,crew,horse,injury,leader,crewtype,gold
from general where owner=%i',
$userID
);
$query = "select no,nation,level,personal,special2,level,city,crew,horse,injury,leader,crewtype,gold from general where owner='{$userID}'";
$result = MYDB_query($query, $connect) or Error("aaa_processing.php ".MYDB_error($connect),"");
$me = MYDB_fetch_array($result);
$query = "select level,tech from nation where nation='{$me['nation']}'";
$result = MYDB_query($query, $connect) or Error("process53 ".MYDB_error($connect),"");
$nation = MYDB_fetch_array($result);
if($me['level'] == 12) {
$lbonus = $nation['level'] * 2;
} elseif($me['level'] >= 5) {
$lbonus = $nation['level'];
} else {
$lbonus = 0;
[$nationLevel, $tech] = $db->queryFirstList('SELECT level,tech FROM nation WHERE nation=%i', $me['nation']);
if(!$nationLevel){
$nationLevel = 0;
}
if(!$tech){
$tech = 0;
}
$lbonus = setLeadershipBonus($me, $nationLevel);
$ownCities = [];
$ownRegions = [];
$relativeYear = $gameStor->year - $gameStor->startyear;
$tech = $nation['tech'];
[$year, $startyear] = $gameStor->getValuesAsArray(['year','startyear']);
$relativeYear = $year - $startyear;
foreach(DB::db()->query('SELECT city, region from city where nation = %i', $me['nation']) as $city){
$ownCities[$city['city']] = 1;
$ownRegions[$city['region']] = 1;
}
$leader = intdiv($me['leader'] * (100 - $me['injury']), 100) + getHorseEff($me['horse']) + $lbonus;
$crew = $leader - Util::round($me['crew']/100);
$abil = getTechAbil($nation['tech']);
$cost = getTechCost($nation['tech']);
echo "
<font size=2>병사를 모집합니다. 훈련과 사기치는 낮지만 가격이 저렴합니다.<br>
가능한 수보다 많게 입력하면 가능한 최대 병사를 모집합니다.<br>
이미 병사가 있는 경우 추가징병되며, 병종이 다를경우는 기존의 병사는 소집해제됩니다.<br>
현재 징병 가능한 병종은 <font color=green>녹색</font>으로 표시되며,<br>
현재 징병 가능한 특수병종은 <font color=limegreen>초록색</font>으로 표시됩니다.<br>
<script type='text/javascript'>
function calc(cost, formnum) {
switch(formnum) {
case 0: form = document.form0; break;
case 1: form = document.form1; break;
case 2: form = document.form2; break;
case 3: form = document.form3; break;
case 4: form = document.form4; break;
case 5: form = document.form5; break;
case 10: form = document.form10; break;
case 11: form = document.form11; break;
case 12: form = document.form12; break;
case 13: form = document.form13; break;
case 14: form = document.form14; break;
case 20: form = document.form20; break;
case 21: form = document.form21; break;
case 22: form = document.form22; break;
case 23: form = document.form23; break;
case 24: form = document.form24; break;
case 25: form = document.form25; break;
case 26: form = document.form26; break;
case 27: form = document.form27; break;
case 30: form = document.form30; break;
case 31: form = document.form31; break;
case 32: form = document.form32; break;
case 33: form = document.form33; break;
case 34: form = document.form34; break;
case 35: form = document.form35; break;
case 36: form = document.form36; break;
case 37: form = document.form37; break;
case 38: form = document.form38; break;
case 40: form = document.form40; break;
case 41: form = document.form41; break;
case 42: form = document.form42; break;
case 43: form = document.form43; break;
}
crew = form.double.value;
form.cost.value = Math.round(crew * cost);
}
</script>
<table class='tb_layout' style='margin:auto;'>
<tr>
<td colspan=10 align=center id=bg2>
현재 기술력 : <input type=text style=text-align:right;color:white;background-color:black size=5 readonly value=".getTechCall($nation['tech']).">
현재 통솔 : <input type=text style=text-align:right;color:white;background-color:black size=3 readonly value=$leader>
현재 병종 : <input type=text size=8 style=text-align:right;color:white;background-color:black readonly value=".GameUnitConst::byID($me['crewtype'])->name.">
현재 병사 : <input type=text size=5 style=text-align:right;color:white;background-color:black readonly value={$me['crew']}>
현재 자금 : <input type=text size=5 style=text-align:right;color:white;background-color:black readonly value={$me['gold']}>
</td>
</tr>
<tr>
<td width=64 align=center id=bg1>사진</td>
<td width=64 align=center id=bg1>병종</td>
<td width=40 align=center id=bg1>공격</td>
<td width=40 align=center id=bg1>방어</td>
<td width=40 align=center id=bg1>기동</td>
<td width=40 align=center id=bg1>회피</td>
<td width=40 align=center id=bg1>군량</td>
<td width=40 align=center id=bg1>가격</td>
<td width=130 align=center id=bg1>병사수</td>
<td width=300 align=center id=bg1>특징</td>
</tr>";
$leader = getGeneralLeadership($me, true, true, true);
$fullLeader = getGeneralLeadership($me, false, true, true);
$abil = getTechAbil($tech);
foreach(GameUnitConst::all() as $i=>$unit) {
if($i == 0){
echo '<tr><td colspan=10>보병 계열</td></tr>';
}
else if($i == 10){
echo '<tr><td colspan=10>궁병 계열</td></tr>';
}
else if($i == 20){
echo '<tr><td colspan=10>기병 계열</td></tr>';
}
else if($i == 30){
echo '<tr><td colspan=10>귀병 계열</td></tr>';
}
else if($i == 40){
echo '<tr><td colspan=10>차병 계열</td></tr>';
}
$armTypes = [];
if(!$unit->isValid($ownCities, $ownRegions, $relativeYear, $tech)){
continue; //TODO: 불가능한 병종도 보여줄 필요가 있음.
}
foreach(GameUnitConst::allType() as $armType => $armName){
$armTypeCrews = [];
if($unit->recruitType == 0){
$l = 'green';
}
else{
$l = 'limegreen';
}
$baseRice = $unit->rice * $cost;
$baseCost = $unit->cost * $cost;
$baseCost = CharCost($baseCost, $me['personal']);
$unitBaseType = intdiv($unit->id, 10);
if($me['special2'] == 50 && $unitBaseType == 0){
$baseCost *= 0.9;
}
else if($me['special2'] == 51 && $unitBaseType == 1){
$baseCost *= 0.9;
}
else if($me['special2'] == 52 && $unitBaseType == 2){
$baseCost *= 0.9;
}
else if($me['special2'] == 53 && $unitBaseType == 3){
$baseCost *= 0.9;
}
else if($me['special2'] == 54 && $unitBaseType == 4){
$baseCost *= 0.9;
}
else if($me['special2'] == 72) {
$baseCost *= 0.5;
}
$name = $unit->name;
$attack = $unit->attack + $abil;
$defence = $unit->defence + $abil;
$speed = $unit->speed;
$avoid = $unit->avoid;
$weapImage = ServConfig::$gameImagePath."/weap{$i}.png";
if($gameStor->show_img_level < 2) { $weapImage = ServConfig::$sharedIconPath."/default.jpg"; }
$baseRiceShort = round($baseRice, 1);
$baseCostShort = round($baseCost, 1);
$info = join('<br>', $unit->info);
echo "
<tr height=64 bgcolor=$l>
<td style='background:no-repeat center url(\"{$weapImage}\");background-size:64px;background-color:#222222;' align=center></td>
<td align=center>{$name}</td>
<td align=center>{$attack}</td>
<td align=center>{$defence}</td>
<td align=center>{$speed}</td>
<td align=center>{$avoid}</td>
<td align=center>{$baseRiceShort}</td>
<td align=center>{$baseCostShort}</td>
<form name=form{$i} action=c_double.php>
<td valign=center>
<input type=text name=double maxlength=3 size=3 value=$crew style=text-align:right;color:white;background-color:black>00<input type=button value=계산 onclick='calc($baseCost, $i)'><br>
<input type=text name=cost maxlength=5 size=5 readonly style=text-align:right;color:white;background-color:black> <input type=submit value=징병>
<input type=hidden name=third value={$i}>
<input type=hidden name=command value=$command>";
for($j=0; $j < count($turn); $j++) {
echo "
<input type=hidden name=turn[] value=$turn[$j]>";
}
echo "
</td>
</form>
<td>$info</td>
</tr>";
}
echo "
</table>";
ender();
}
function command_12($turn, $command) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
$userID = Session::getUserID();
starter("모병");
$query = "select no,nation,level,personal,special2,level,city,crew,horse,injury,leader,crewtype,gold from general where owner='{$userID}'";
$result = MYDB_query($query, $connect) or Error("aaa_processing.php ".MYDB_error($connect),"");
$me = MYDB_fetch_array($result);
$query = "select level,tech from nation where nation='{$me['nation']}'";
$result = MYDB_query($query, $connect) or Error("process53 ".MYDB_error($connect),"");
$nation = MYDB_fetch_array($result);
if($me['level'] == 12) {
$lbonus = $nation['level'] * 2;
} elseif($me['level'] >= 5) {
$lbonus = $nation['level'];
} else {
$lbonus = 0;
}
$ownCities = [];
$ownRegions = [];
$relativeYear = $gameStor->year - $gameStor->startyear;
$tech = $nation['tech'];
foreach(DB::db()->query('SELECT city, region from city where nation = %i', $me['nation']) as $city){
$ownCities[$city['city']] = 1;
$ownRegions[$city['region']] = 1;
}
$leader = intdiv($me['leader'] * (100 - $me['injury']), 100) + getHorseEff($me['horse']) + $lbonus;
$crew = $leader - round($me['crew']/100);
$abil = getTechAbil($nation['tech']);
$cost = getTechCost($nation['tech']);
echo "
<font size=2>병사를 모집합니다. 훈련과 사기치는 높지만 자금이 많이 듭니다.<br>
가능한 수보다 많게 입력하면 가능한 최대 병사를 모집합니다.<br>
이미 병사가 있는 경우 추가징병되며, 병종이 다를경우는 기존의 병사는 소집해제됩니다.<br>
현재 모병 가능한 병종은 <font color=green>녹색</font>으로 표시되며,<br>
현재 모병 가능한 특수병종은 <font color=limegreen>초록색</font>으로 표시됩니다.<br>
<script type='text/javascript'>
function calc(cost, formnum) {
switch(formnum) {
case 0: form = document.form0; break;
case 1: form = document.form1; break;
case 2: form = document.form2; break;
case 3: form = document.form3; break;
case 4: form = document.form4; break;
case 5: form = document.form5; break;
case 10: form = document.form10; break;
case 11: form = document.form11; break;
case 12: form = document.form12; break;
case 13: form = document.form13; break;
case 14: form = document.form14; break;
case 20: form = document.form20; break;
case 21: form = document.form21; break;
case 22: form = document.form22; break;
case 23: form = document.form23; break;
case 24: form = document.form24; break;
case 25: form = document.form25; break;
case 26: form = document.form26; break;
case 27: form = document.form27; break;
case 30: form = document.form30; break;
case 31: form = document.form31; break;
case 32: form = document.form32; break;
case 33: form = document.form33; break;
case 34: form = document.form34; break;
case 35: form = document.form35; break;
case 36: form = document.form36; break;
case 37: form = document.form37; break;
case 38: form = document.form38; break;
case 40: form = document.form40; break;
case 41: form = document.form41; break;
case 42: form = document.form42; break;
case 43: form = document.form43; break;
}
crew = form.double.value;
form.cost.value = Math.round(crew * cost * 2);
}
</script>
<table class='tb_layout' style='margin:auto;'>
<tr><td align=center colspan=10>모병은 가격 2배의 자금이 소요됩니다.</td></tr>
<tr>
<td colspan=10 align=center id=bg2>
현재 기술력 : <input type=text style=text-align:right;color:white;background-color:black size=5 readonly value=".getTechCall($nation['tech']).">
현재 통솔 : <input type=text style=text-align:right;color:white;background-color:black size=3 readonly value=$leader>
현재 병종 : <input type=text size=8 style=text-align:right;color:white;background-color:black readonly value=".GameUnitConst::byID($me['crewtype'])->name.">
현재 병사 : <input type=text size=5 style=text-align:right;color:white;background-color:black readonly value={$me['crew']}>
현재 자금 : <input type=text size=5 style=text-align:right;color:white;background-color:black readonly value={$me['gold']}>
</td>
</tr>
<tr>
<td width=64 align=center id=bg1>사진</td>
<td width=64 align=center id=bg1>병종</td>
<td width=40 align=center id=bg1>공격</td>
<td width=40 align=center id=bg1>방어</td>
<td width=40 align=center id=bg1>기동</td>
<td width=40 align=center id=bg1>회피</td>
<td width=40 align=center id=bg1>군량</td>
<td width=40 align=center id=bg1>가격</td>
<td width=130 align=center id=bg1>병사수</td>
<td width=300 align=center id=bg1>특징</td>
</tr>";
foreach(GameUnitConst::byType($armType) as $unit){
$crewObj = new \stdClass;
if(!$unit->isValid($ownCities, $ownRegions, $relativeYear, $tech)){
continue; //TODO: 불가능한 병종도 보여줄 필요가 있음.
}
$crewObj->id = $unit->id;
if($unit->reqTech == 0){
$crewObj->bgcolor = 'green';
}
else{
$crewObj->bgcolor = 'limegreen';
}
foreach(GameUnitConst::all() as $i=>$unit) {
if($i == 0){
echo '<tr><td colspan=10>보병 계열</td></tr>';
}
else if($i == 10){
echo '<tr><td colspan=10>궁병 계열</td></tr>';
}
else if($i == 20){
echo '<tr><td colspan=10>기병 계열</td></tr>';
}
else if($i == 30){
echo '<tr><td colspan=10>귀병 계열</td></tr>';
}
else if($i == 40){
echo '<tr><td colspan=10>차병 계열</td></tr>';
}
$crewObj->baseRice = $unit->rice * getTechCost($tech);
$crewObj->baseCost = CharCost($unit->costWithTech($tech), $me['personal']);
if(!$unit->isValid($ownCities, $ownRegions, $relativeYear, $tech)){
continue; //TODO: 불가능한 병종도 보여줄 필요가 있음.
}
if($unit->recruitType == 0){
$l = 'green';
}
else{
$l = 'limegreen';
}
$armType = $unit->armType;
if($me['special2'] == 50 && $armType == GameUnitConst::T_FOOTMAN){
$crewObj->baseCost *= 0.9;
}
else if($me['special2'] == 51 && $armType == GameUnitConst::T_ARCHER){
$crewObj->baseCost *= 0.9;
}
else if($me['special2'] == 52 && $armType == GameUnitConst::T_CAVALRY){
$crewObj->baseCost *= 0.9;
}
else if($me['special2'] == 53 && $armType == GameUnitConst::T_WIZARD){
$crewObj->baseCost *= 0.9;
}
else if($me['special2'] == 54 && $armType == GameUnitConst::T_SIEGE){
$crewObj->baseCost *= 0.9;
}
else if($me['special2'] == 72) {
$crewObj->baseCost *= 0.5;
}
$crewObj->name = $unit->name;
$crewObj->attack = $unit->attack + $abil;
$crewObj->defence = $unit->defence + $abil;
$crewObj->speed = $unit->speed;
$crewObj->avoid = $unit->avoid;
if($gameStor->show_img_level < 2) {
$crewObj->img = ServConfig::$sharedIconPath."/default.jpg";
}
else{
$crewObj->img = ServConfig::$gameImagePath."/weap".$unit->id.".png";
}
$crewObj->baseRiceShort = round($crewObj->baseRice, 1);
$crewObj->baseCostShort = round($crewObj->baseCost, 1);
$crewObj->info = join('<br>', $unit->info);
$baseRice = $unit->rice * $cost;
$baseCost = $unit->cost * $cost;
$baseCost = CharCost($baseCost, $me['personal']);
$unitBaseType = intdiv($unit->id, 10);
if($me['special2'] == 50 && $unitBaseType == 0){
$baseCost *= 0.9;
$armTypeCrews[] = $crewObj;
}
else if($me['special2'] == 51 && $unitBaseType == 1){
$baseCost *= 0.9;
}
else if($me['special2'] == 52 && $unitBaseType == 2){
$baseCost *= 0.9;
}
else if($me['special2'] == 53 && $unitBaseType == 3){
$baseCost *= 0.9;
}
else if($me['special2'] == 54 && $unitBaseType == 4){
$baseCost *= 0.9;
}
else if($me['special2'] == 72) {
$baseCost *= 0.5;
}
$name = $unit->name;
$attack = $unit->attack + $abil;
$defence = $unit->defence + $abil;
$speed = $unit->speed;
$avoid = $unit->avoid;
$weapImage = ServConfig::$gameImagePath."/weap{$i}.png";
if($gameStor->show_img_level < 2) { $weapImage = ServConfig::$sharedIconPath."/default.jpg"; }
$baseRiceShort = round($baseRice, 1);
$baseCostShort = round($baseCost, 1);
$info = join('<br>', $unit->info);
echo "
<tr height=64 bgcolor=$l>
<td style='background:no-repeat center url(\"{$weapImage}\");background-size:64px;background-color:#222222;' align=center></td>
<td align=center>{$name}</td>
<td align=center>{$attack}</td>
<td align=center>{$defence}</td>
<td align=center>{$speed}</td>
<td align=center>{$avoid}</td>
<td align=center>{$baseRiceShort}</td>
<td align=center>{$baseCostShort}</td>
<form name=form{$i} action=c_double.php>
<td valign=center>
<input type=text name=double maxlength=3 size=3 value=$crew style=text-align:right;color:white;background-color:black>00<input type=button value=계산 onclick='calc($baseCost, $i)'><br>
<input type=text name=cost maxlength=5 size=5 readonly style=text-align:right;color:white;background-color:black> <input type=submit value=모병>
<input type=hidden name=third value={$i}>
<input type=hidden name=command value=$command>";
for($j=0; $j < count($turn); $j++) {
echo "
<input type=hidden name=turn[] value=$turn[$j]>";
}
echo "
</td>
</form>
<td>$info</td>
</tr>";
$armTypes[] = [$armName, $armTypeCrews];
}
if($is모병){
$commandName = '모병';
starter("모병");
}
else{
$commandName = '징병';
starter("징병");
}
echo "
</table>";
$templates = new \League\Plates\Engine('templates');
echo $templates->render('recruitCrewForm', [
'command'=>$command,
'commandName'=>$commandName,
'techLevelText'=>getTechCall($tech),
'tech'=>$tech,
'leader'=>$leader,
'fullLeader'=>$fullLeader,
'crewType'=>GameUnitConst::byId($me['crewtype'])->id,
'crewTypeName'=>GameUnitConst::byId($me['crewtype'])->name,
'crew'=>$me['crew'],
'gold'=>$me['gold'],
'turn'=>$turn,
'armTypes'=>$armTypes,
]);
ender();
}
@@ -984,7 +708,7 @@ function command_25($turn, $command) {
!!! 방랑군을 포함한 랜덤임관입니다. 유니크를 기대하신다면!<br>
??? 방랑군을 제외한 랜덤임관입니다. 유니크 혜택은 없습니다.<br>
임관 금지이거나 초기 제한중인 국가는 붉은색 배경으로 표시됩니다.<br>
870px x 200px 넘는 높이를 점유할 통보없이 제한될 습니다.<br>
870px x 200px를 넘어서는 내용은 표시되지 습니다.<br>
<form name=form1 action=c_double.php method=post>
<select name=double size=1 style=color:white;background-color:black>
<option value=99 style=color:white;background-color:black;>!!!</option>
+297
View File
@@ -0,0 +1,297 @@
<?php
namespace sammo;
class ActionLogger{
protected $generalId;
protected $nationId;
protected $autoFlush;
protected $year = null;
protected $month = null;
protected $generalHistoryLog = [];
protected $generalActionLog = [];
protected $generalBattleResultLog = [];
protected $generalBattleDetailLog = [];
protected $nationalHistoryLog = [];
protected $globalHistoryLog = [];
protected $globalActionLog = [];
const RAWTEXT = 0;
const PLAIN = 1;
const YEAR_MONTH = 2;
const YEAR = 3;
const MONTH = 4;
const EVENT_PLAIN = 5;
const EVENT_YEAR_MONTH = 6;
const NOTICE = 7;
const NOTICE_YEAR_MONTH = 8;
public function __construct(int $generalId, int $nationId, int $year, int $month, bool $autoFlush = true){
$this->generalId = $generalId;
$this->nationId = $nationId;
$this->year = $year;
$this->month = $month;
$this->autoFlush = $autoFlush;
}
public function __destruct(){
if($this->autoFlush){
$this->flush();
}
}
public function rollback(){
$this->generalHistoryLog = [];
$this->generalActionLog = [];
$this->generalBattleResultLog = [];
$this->generalBattleDetailLog = [];
$this->nationalHistoryLog = [];
$this->globalHistoryLog = [];
$this->globalActionLog = [];
}
public function flush(){
$db = DB::db();
if($this->generalHistoryLog){
$rawText = join('<br>', $this->generalHistoryLog).'<br>';
$db->update('general', [
'history'=>$db->sqleval('concat(%s, history)', $rawText)
], 'no=%i', $this->generalId);
$this->generalHistoryLog = [];
}
if($this->generalActionLog){
pushGenLog(['no'=>$this->generalId], $this->generalActionLog);
$this->generalActionLog = [];
}
if($this->generalBattleResultLog){
pushBatRes(['no'=>$this->generalId], $this->generalBattleResultLog);
$this->generalBattleResultLog = [];
}
if($this->generalBattleDetailLog){
pushBatLog(['no'=>$this->generalId], $this->generalBattleDetailLog);
$this->generalBattleDetailLog = [];
}
if($this->nationId && $this->nationalHistoryLog){
$rawText = join('<br>', $this->nationalHistoryLog).'<br>';
$db->update('nation', [
'history'=>$db->sqleval('concat(%s, history)', $rawText)
], 'nation=%i', $this->nationId);
$this->nationalHistoryLog = [];
}
if($this->globalHistoryLog){
pushWorldHistory($this->globalHistoryLog, $this->year, $this->month);
$this->globalHistoryLog = [];
}
if($this->globalActionLog){
pushGeneralPublicRecord($this->globalActionLog, $this->year, $this->month);
$this->globalActionLog = [];
}
}
public function pushGeneralHistoryLog($text, int $formatType = self::YEAR_MONTH){
if(!$text){
return;
}
if(is_array($text)){
foreach($text as $textItem){
$this->pushGeneralHistoryLog($textItem);
}
return;
}
$text = $this->formatText($text, $formatType);
$this->generalHistoryLog[] = $text;
}
public function pushGeneralActionLog($text, int $formatType = self::MONTH){
if(!$text){
return;
}
if(is_array($text)){
foreach($text as $textItem){
$this->pushGeneralActionLog($textItem);
}
return;
}
$text = $this->formatText($text, $formatType);
$this->generalActionLog[] = $text;
}
public function pushGeneralBattleResultLog($text, int $formatType = self::RAWTEXT){
if(!$text){
return;
}
if(is_array($text)){
foreach($text as $textItem){
$this->pushGeneralBattleResultLog($textItem);
}
return;
}
$text = $this->formatText($text, $formatType);
$this->generalBattleResultLog[] = $text;
}
public function pushGeneralBattleDetailLog($text, int $formatType = self::PLAIN){
if(!$text){
return;
}
if(is_array($text)){
foreach($text as $textItem){
$this->pushGeneralBattleDetailLog($textItem);
}
return;
}
$text = $this->formatText($text, $formatType);
$this->generalBattleDetailLog[] = $text;
}
public function pushNationalHistoryLog($text, int $formatType = self::RAWTEXT){
if(!$text){
return;
}
if(is_array($text)){
foreach($text as $textItem){
$this->pushNationalHistoryLog($textItem);
}
return;
}
$text = $this->formatText($text, $formatType);
$this->nationalHistoryLog[] = $text;
}
public function pushGlobalActionLog($text, int $formatType = self::MONTH){
if(!$text){
return;
}
if(is_array($text)){
foreach($text as $textItem){
$this->pushGlobalActionLog($textItem);
}
return;
}
$text = $this->formatText($text, $formatType);
$this->globalActionLog[] = $text;
}
public function pushGlobalHistoryLog($text, int $formatType = self::YEAR_MONTH){
if(!$text){
return;
}
if(is_array($text)){
foreach($text as $textItem){
$this->pushGlobalHistoryLog($textItem);
}
return;
}
$text = $this->formatText($text, $formatType);
$this->globalHistoryLog[] = $text;
}
public function formatText(string $text, int $formatType):string{
if($formatType === self::RAWTEXT){
return $text;
}
if($formatType === self::PLAIN){
return "<C>●</>{$text}";
}
if($formatType === self::YEAR_MONTH){
return "<C>●</>{$this->year}{$this->month}월:{$text}";
}
if($formatType === self::YEAR){
return "<C>●</>{$this->year}년:{$text}";
}
if($formatType === self::MONTH){
return "<C>●</>{$this->month}월:{$text}";
}
if($formatType === self::EVENT_PLAIN){
return "<S>◆</>{$text}";
}
if($formatType === self::EVENT_YEAR_MONTH){
return "<S>◆</>{$this->year}{$this->month}월:{$text}";
}
if($formatType === self::NOTICE){
return "<R>★</>{$text}";
}
if($formatType === self::NOTICE_YEAR_MONTH){
return "<R>★</>{$this->year}{$this->month}월:{$text}";
}
return $text;
}
public function pushBattleResultTemplate(
WarUnit $me,
WarUnit $oppose
){
if($me instanceof WarUnitCity){
return;
}
$templates = new \League\Plates\Engine(__dir__.'/../templates');
$render_me = [
'crewtype' => $me->getCrewTypeShortName(),
'name' => $me->getName(),
'remain_crew' => $me->getHP(),
'killed_crew' => -$me->getDeadCurrentBattle()
];
$render_oppose = [
'crewtype' => $oppose->getCrewTypeShortName(),
'name' => $oppose->getName(),
'remain_crew' => $oppose->getHP(),
'killed_crew' => -$oppose->getDeadCurrentBattle()
];
if(!$me->isAttacker()){
$warType = 'defense';
$warTypeStr = '←';
}
else if($oppose instanceof WarUnitCity){
$warType = 'siege';
$warTypeStr = '→';
}
else{
$warType = 'attack';
$warTypeStr = '→';
}
$res = str_replace(["\r\n", "\r", "\n"], '', $templates->render('small_war_log',[
'year'=>$this->year,
'month'=>$this->month,
'war_type'=>$warType,
'war_type_str'=>$warTypeStr,
'me' => $render_me,
'you' => $render_oppose,
]));
$this->pushGeneralBattleResultLog($res, self::EVENT_YEAR_MONTH);
$this->pushGeneralBattleDetailLog($res, self::EVENT_YEAR_MONTH);
$this->pushGeneralActionLog($res, self::EVENT_YEAR_MONTH);
}
}
-357
View File
@@ -1,357 +0,0 @@
<?php
namespace sammo;
class CityConst{
private function __construct(){
}
private static $constID = null;
private static $constName = null;
private static $constRegion = null;
public static $regionMap = [
'하북'=>1,1=>'하북',
'중원'=>2,2=>'중원',
'서북'=>3,3=>'서북',
'서촉'=>4,4=>'서촉',
'남중'=>5,5=>'남중',
'초'=>6,6=>'초',
'오월'=>7,7=>'오월',
'동이'=>8,8=>'동이'
];
public static $levelMap = [
'수'=>1,1=>'수',
'진'=>2,2=>'진',
'관'=>3,3=>'관',
'이'=>4,4=>'이',
'소'=>5,5=>'소',
'중'=>6,6=>'중',
'대'=>7,7=>'대',
'특'=>8,8=>'특'
];
/**
* @return \sammo\CityInitialDetail[]
*/
public static function all(){
static::_generate();
return static::$constID;
}
public static function byID(int $id): CityInitialDetail{
static::_generate();
return static::$constID[$id];
}
public static function byName(string $name): CityInitialDetail{
static::_generate();
return static::$constName[$name];
}
public static function byRegion(int $region): CityInitialDetail{
static::_generate();
return static::$constRegion[$region];
}
private static $initCity = [
//id, 도시, 규모, 인구, 농, 상, 치, 성, 수,(x100) 지역, 연결도시
[ 1, '업', '특', 6205, 125, 113, 100, 117, 122, '하북', ['남피', '복양', '호관', '계교', '관도']],
[ 2, '허창', '특', 5876, 121, 124, 100, 117, 125, '중원', ['완', '진류', '초', '호로', '사수', '관도']],
[ 3, '낙양', '특', 8357, 117, 120, 100, 121, 124, '중원', ['호관', '호로', '사곡', '사수']],
[ 4, '장안', '특', 5923, 116, 123, 100, 120, 118, '서북', ['안정', '함곡', '기산']],
[ 5, '성도', '특', 6525, 123, 125, 100, 125, 123, '서촉', ['덕양', '강주', '면죽']],
[ 6, '양양', '특', 5837, 120, 126, 100, 115, 117, '초', ['신야', '장판']],
[ 7, '건업', '특', 6386, 116, 123, 100, 115, 119, '오월', ['오', '합비', '광릉']],
[ 8, '북평', '대', 4862, 102, 95, 80, 103, 99, '하북', ['역경', '백랑']],
[ 9, '남피', '대', 5032, 99, 101, 80, 101, 105, '하북', ['업', '평원', '역경']],
[10, '완', '대', 4724, 103, 100, 80, 101, 99, '중원', ['허창', '여남', '신야', '호로']],
[11, '수춘', '대', 5143, 99, 96, 80, 99, 95, '중원', ['서주', '여남', '초', '합비']],
[12, '서주', '대', 4853, 101, 98, 80, 102, 97, '중원', ['수춘', '하비', '초', '패']],
[13, '강릉', '대', 4850, 105, 96, 80, 95, 96, '초', ['장사', '무릉', '이릉', '장판']],
[14, '장사', '대', 4710, 97, 99, 80, 100, 105, '초', ['강릉', '시상', '계양', '무릉', '영릉']],
[15, '시상', '대', 5252, 98, 100, 100, 99, 96, '오월', ['장사', '여강', '고창', '적벽', '파양']],
[16, '위례', '대', 4926, 100, 93, 80, 98, 103, '동이', ['평양', '사비', '계림', '안평', '동황']],
[17, '계', '중', 3885, 75, 80, 60, 78, 81, '하북', ['진양', '역경']],
[18, '복양', '중', 4185, 80, 83, 60, 82, 80, '중원', ['업', '진류', '계교', '정도']],
[19, '진류', '중', 3957, 82, 80, 60, 80, 83, '중원', ['허창', '복양', '사수', '관도', '정도']],
[20, '여남', '중', 3831, 77, 81, 60, 84, 77, '중원', ['완', '수춘', '초']],
[21, '하비', '중', 4278, 85, 83, 60, 82, 78, '중원', ['서주', '광릉']],
[22, '서량', '중', 3874, 77, 79, 60, 83, 80, '서북', ['천수', '강', '저']],
[23, '하내', '중', 3736, 77, 81, 60, 81, 80, '서북', ['진양', '홍농', '흉노', '호관']],
[24, '한중', '중', 4027, 77, 84, 60, 80, 85, '서촉', ['상용', '양평', '기산']],
[25, '상용', '중', 3687, 78, 76, 60, 77, 81, '서촉', ['한중', '신야']],
[26, '덕양', '중', 3803, 81, 84, 60, 79, 77, '서촉', ['성도', '강주', '자동', '영안']],
[27, '강주', '중', 4126, 79, 80, 60, 84, 81, '서촉', ['성도', '덕양', '영안', '귀양', '주시']],
[28, '건녕', '중', 3765, 82, 80, 60, 86, 81, '남중', ['귀양', '운남', '남영']],
[29, '남해', '중', 3803, 82, 76, 60, 80, 81, '남중', ['교지', '상동', '대', '산월']],
[30, '계양', '중', 3955, 83, 80, 60, 81, 77, '초', ['장사', '영릉', '상동']],
[31, '오', '중', 4355, 77, 81, 60, 77, 76, '오월', ['건업', '회계', '파양', '탐라']],
[32, '평양', '중', 3982, 78, 80, 60, 83, 78, '동이', ['위례', '졸본']],
[33, '사비', '중', 4157, 77, 79, 60, 78, 80, '동이', ['위례', '계림', '탐라']],
[34, '계림', '중', 3911, 80, 74, 60, 81, 78, '동이', ['위례', '사비', '이도', '탐라']],
[35, '진양', '소', 3074, 56, 59, 40, 64, 59, '하북', ['계', '하내', '호관']],
[36, '평원', '소', 3074, 62, 65, 40, 61, 63, '하북', ['남피', '북해', '계교']],
[37, '북해', '소', 3146, 55, 63, 40, 63, 58, '하북', ['평원', '패', '동황']],
[38, '초', '소', 3286, 60, 62, 40, 62, 57, '중원', ['허창', '수춘', '서주', '여남', '정도']],
[39, '패', '소', 2877, 64, 58, 40, 58, 59, '중원', ['서주', '북해', '정도']],
[40, '천수', '소', 2985, 59, 64, 40, 60, 58, '서북', ['서량', '안정', '저', '적도']],
[41, '안정', '소', 2764, 57, 59, 40, 57, 62, '서북', ['장안', '천수', '가정']],
[42, '홍농', '소', 2748, 57, 63, 40, 58, 63, '서북', ['하내', '사곡', '함곡']],
[43, '하변', '소', 2785, 58, 62, 40, 60, 56, '서촉', ['가맹', '가정']],
[44, '자동', '소', 2870, 57, 55, 40, 60, 58, '서촉', ['덕양', '양평', '가맹', '면죽']],
[45, '영안', '소', 3153, 62, 59, 40, 58, 59, '서촉', ['덕양', '강주', '이릉']],
[46, '귀양', '소', 2746, 58, 61, 40, 61, 58, '남중', ['강주', '건녕', '주시']],
[47, '주시', '소', 2828, 60, 59, 40, 58, 63, '남중', ['강주', '귀양', '운남']],
[48, '운남', '소', 3258, 62, 60, 40, 64, 61, '남중', ['건녕', '주시', '남만']],
[49, '남영', '소', 2853, 59, 62, 40, 58, 57, '남중', ['건녕', '영릉', '남만']],
[50, '교지', '소', 3195, 58, 59, 40, 58, 59, '남중', ['남해', '남만']],
[51, '신야', '소', 2786, 60, 62, 40, 58, 55, '초', ['양양', '완', '상용']],
[52, '강하', '소', 3074, 55, 56, 40, 57, 60, '초', ['장판', '적벽']],
[53, '무릉', '소', 3196, 58, 63, 40, 63, 58, '초', ['강릉', '장사', '영릉']],
[54, '영릉', '소', 2849, 62, 58, 40, 62, 62, '초', ['장사', '계양', '남영', '무릉']],
[55, '상동', '소', 2767, 58, 59, 40, 62, 58, '초', ['남해', '계양', '고창']],
[56, '여강', '소', 2905, 56, 58, 40, 60, 55, '오월', ['시상', '합비', '적벽', '파양']],
[57, '회계', '소', 3005, 64, 59, 40, 62, 64, '오월', ['오', '산월']],
[58, '고창', '소', 2802, 57, 62, 40, 58, 63, '오월', ['시상', '상동', '산월']],
[59, '대', '소', 3256, 60, 62, 40, 57, 60, '오월', ['남해', '산월', '유구']],
[60, '안평', '소', 2937, 63, 59, 40, 59, 63, '동이', ['위례', '졸본', '동황', '백랑']],
[61, '졸본', '소', 2939, 55, 59, 40, 60, 58, '동이', ['평양', '안평', '오환']],
[62, '이도', '소', 3174, 58, 61, 40, 58, 56, '동이', ['계림', '왜', '탐라']],
[63, '강', '이', 2095, 40, 42, 20, 43, 40, '서북', ['서량', '적도']],
[64, '저', '이', 1957, 40, 42, 20, 43, 42, '서북', ['서량', '천수', '가정']],
[65, '흉노', '이', 2064, 40, 41, 20, 40, 38, '서북', ['하내', '적도']],
[66, '남만', '이', 2378, 40, 42, 20, 43, 45, '남중', ['운남', '남영', '교지']],
[67, '산월', '이', 2275, 40, 37, 20, 43, 38, '오월', ['남해', '회계', '고창', '대']],
[68, '오환', '이', 2153, 42, 37, 20, 43, 40, '동이', ['졸본', '백랑']],
[69, '왜', '이', 2065, 39, 37, 20, 43, 41, '동이', ['이도', '유구']],
[70, '호관', '관', 887, 19, 18, 20, 95, 96, '하북', ['업', '낙양', '하내', '진양']],
[71, '호로', '관', 1112, 22, 21, 20, 103, 98, '중원', ['허창', '낙양', '완']],
[72, '사곡', '관', 1008, 21, 19, 20, 99, 101, '서북', ['낙양', '홍농']],
[73, '함곡', '관', 1081, 20, 22, 20, 101, 102, '서북', ['장안', '홍농']],
[74, '사수', '관', 958, 17, 19, 20, 95, 96, '중원', ['허창', '낙양', '진류', '관도']],
[75, '양평', '관', 868, 19, 19, 20, 97, 96, '서촉', ['한중', '자동', '기산']],
[76, '가맹', '관', 855, 17, 18, 20, 96, 95, '서촉', ['하변', '자동']],
[77, '역경', '진', 985, 18, 19, 20, 39, 41, '하북', ['북평', '남피', '계']],
[78, '계교', '진', 1012, 21, 19, 20, 40, 42, '하북', ['업', '복양', '평원']],
[79, '동황', '진', 992, 19, 21, 20, 38, 40, '하북', ['위례', '북해', '안평']],
[80, '관도', '진', 1123, 22, 20, 20, 42, 43, '중원', ['업', '허창', '진류', '사수']],
[81, '정도', '진', 1085, 21, 21, 20, 41, 38, '중원', ['복양', '진류', '초', '패']],
[82, '합비', '진', 998, 20, 19, 20, 39, 41, '중원', ['건업', '수춘', '여강']],
[83, '광릉', '진', 1001, 20, 21, 20, 41, 40, '중원', ['건업', '하비']],
[84, '적도', '진', 952, 18, 17, 20, 38, 37, '서북', ['천수', '강', '흉노']],
[85, '가정', '진', 931, 17, 17, 20, 36, 38, '서북', ['안정', '하변', '저']],
[86, '기산', '진', 1005, 19, 18, 20, 41, 40, '서촉', ['장안', '한중', '양평']],
[87, '면죽', '관', 1093, 22, 21, 20, 108, 99, '서촉', ['성도', '자동']],
[88, '이릉', '진', 968, 18, 19, 20, 39, 41, '초', ['강릉', '영안']],
[89, '장판', '진', 1032, 21, 20, 20, 40, 37, '초', ['양양', '강릉', '강하', '적벽']],
[90, '백랑', '진', 1052, 22, 19, 20, 38, 42, '동이', ['북평', '안평', '오환']],
[91, '적벽', '수', 1117, 23, 21, 20, 42, 41, '오월', ['시상', '강하', '여강', '장판']],
[92, '파양', '수', 1037, 20, 22, 20, 38, 38, '오월', ['시상', '오', '여강']],
[93, '탐라', '수', 1130, 22, 21, 20, 43, 41, '동이', ['오', '사비', '계림', '이도']],
[94, '유구', '수', 921, 17, 18, 20, 37, 37, '동이', ['대', '왜']],
];
private static function _generate(){
if(static::$constID || static::$constName || static::$constRegion){
return;
}
$constID = [];
$constName = [];
$constCity = [];
$constRegion = [];
$nameMap = [];
foreach (static::$initCity as $rawCity) {
$nameMap[$rawCity[1]] = $rawCity[0];
}
foreach (static::$buildInit as $key=>$val){
$key2 = static::$levelMap[$key];
if(key_exists($key2, static::$buildInit)){
continue;//혹시 모를 버그 방지
}
static::$buildInit[$key2] = $val;
}
foreach(static::$initCity as $rawCity){
list(
$id,
$name,
$level,
$population,
$agriculture,
$commerce,
$security,
$defence,
$wall,
$region,
$path
) = $rawCity;
$level = static::$levelMap[$level];
$population *= 100;
$agriculture *= 100;
$commerce *= 100;
$security *= 100;
$defence *= 100;
$wall *= 100;
$region = static::$regionMap[$region];
$newPath = [];
foreach($path as $pathName){
$pathID = $nameMap[$pathName];
$newPath[$pathID] = $pathName;
}
$city = new CityInitialDetail(
$id,
$name,
$level,
$population,
$agriculture,
$commerce,
$security,
$defence,
$wall,
$region,
$newPath
);
$constID[$id] = $city;
$constName[$name] = $city;
if(!key_exists($region, $constRegion)){
$constRegion[$region] = [];
}
$constRegion[$region] = $city;
}
static::$constID = $constID;
static::$constName = $constName;
static::$constRegion = $constRegion;
}
private static $buildInitCommon = [
'rate'=>50,
'trade'=>100,
'gen1'=>0,
'gen2'=>0,
'gen3'=>0
];
private static $buildInit = [
'수'=>[
'pop' => 5000,
'agri'=> 100,
'comm'=> 100,
'secu'=> 100,
'def' => 500,
'wall'=> 500,
],
'진'=>[
'pop' => 5000,
'agri'=> 100,
'comm'=> 100,
'secu'=> 100,
'def' => 500,
'wall'=> 500,
],
'관'=>[
'pop' => 10000,
'agri'=> 100,
'comm'=> 100,
'secu'=> 100,
'def' => 1000,
'wall'=> 1000,
],
'이'=>[
'pop' => 50000,
'agri'=> 1000,
'comm'=> 1000,
'secu'=> 1000,
'def' => 1000,
'wall'=> 1000,
],
'소'=>[
'pop' =>100000,
'agri'=> 1000,
'comm'=> 1000,
'secu'=> 1000,
'def' => 2000,
'wall'=> 2000,
],
'중'=>[
'pop' =>100000,
'agri'=> 1000,
'comm'=> 1000,
'secu'=> 1000,
'def' => 3000,
'wall'=> 3000,
],
'대'=>[
'pop' =>150000,
'agri'=> 1000,
'comm'=> 1000,
'secu'=> 1000,
'def' => 4000,
'wall'=> 4000,
],
'특'=>[
'pop' =>150000,
'agri'=> 1000,
'comm'=> 1000,
'secu'=> 1000,
'def' => 5000,
'wall'=> 5000,
]
];
private static function test(){
static::_generate();
foreach(static::all() as $id=>$city){
foreach($city->path as $connId=>$connCityText){
$connCity = static::byID($connId);
if(!key_exists($id, $connCity->path)){
throw new \RuntimeException(sprintf('도시 연결이 올바르지 않음! %s <=> %s', $city->name, $connCity->name));
}
}
}
}
public static function build(){
static::_generate();
static::test();
$queries = array_map(function(CityInitialDetail $city){
$initValue = static::$buildInit[$city->level];
$path = join('|', array_keys($city->path));
return [
'city'=>$city->id,
'name'=>$city->name,
'level'=>$city->level,
'path'=>$path,
'pop2'=>$city->population,
'agri2'=>$city->agriculture,
'comm2'=>$city->commerce,
'secu2'=>$city->security,
'def2'=>$city->defence,
'wall2'=>$city->wall,
'region'=>$city->region
] + $initValue + static::$buildInitCommon;
}, array_values(static::$constID));
DB::db()->insert('city', $queries);
}
}
+354
View File
@@ -0,0 +1,354 @@
<?php
namespace sammo;
class CityConstBase{
protected function __construct(){
}
protected static $constID = null;
protected static $constName = null;
protected static $constRegion = null;
public static $regionMap = [
'하북'=>1,1=>'하북',
'중원'=>2,2=>'중원',
'서북'=>3,3=>'서북',
'서촉'=>4,4=>'서촉',
'남중'=>5,5=>'남중',
'초'=>6,6=>'초',
'오월'=>7,7=>'오월',
'동이'=>8,8=>'동이'
];
public static $levelMap = [
'수'=>1,1=>'수',
'진'=>2,2=>'진',
'관'=>3,3=>'관',
'이'=>4,4=>'이',
'소'=>5,5=>'소',
'중'=>6,6=>'중',
'대'=>7,7=>'대',
'특'=>8,8=>'특'
];
/**
* @return \sammo\CityInitialDetail[]
*/
public static function all(){
static::_generate();
return static::$constID;
}
public static function byID(int $id): CityInitialDetail{
static::_generate();
return static::$constID[$id];
}
public static function byName(string $name): CityInitialDetail{
static::_generate();
return static::$constName[$name];
}
public static function byRegion(int $region): CityInitialDetail{
static::_generate();
return static::$constRegion[$region];
}
protected static $initCity = [
//id, 도시, 규모, 인구, 농, 상, 치, 성, 수,(x100)지역, x, y, 연결도시
[ 1, '업', '특', 6205,125,113,100,117,122, '하북', 345, 130, ['남피', '복양', '호관', '계교', '관도']],
[ 2, '허창', '특', 5876,121,124,100,117,125, '중원', 330, 215, ['완', '진류', '초', '호로', '사수', '관도']],
[ 3, '낙양', '특', 8357,117,120,100,121,124, '중원', 275, 180, ['호관', '호로', '사곡', '사수']],
[ 4, '장안', '특', 5923,116,123,100,120,118, '서북', 145, 165, ['안정', '함곡', '기산']],
[ 5, '성도', '특', 6525,123,125,100,125,123, '서촉', 25, 290, ['덕양', '강주', '면죽']],
[ 6, '양양', '특', 5837,120,126,100,115,117, '초', 255, 290, ['신야', '장판']],
[ 7, '건업', '특', 6386,116,123,100,115,119, '오월', 505, 305, ['오', '합비', '광릉']],
[ 8, '북평', '대', 4862,102, 95, 80,103, 99, '하북', 465, 65, ['역경', '백랑']],
[ 9, '남피', '대', 5032, 99,101, 80,101,105, '하북', 395, 95, ['업', '평원', '역경']],
[10, '완', '대', 4724,103,100, 80,101, 99, '중원', 270, 235, ['허창', '여남', '신야', '호로']],
[11, '수춘', '대', 5143, 99, 96, 80, 99, 95, '중원', 395, 270, ['서주', '여남', '초', '합비']],
[12, '서주', '대', 4853,101, 98, 80,102, 97, '중원', 440, 250, ['수춘', '하비', '초', '패']],
[13, '강릉', '대', 4850,105, 96, 80, 95, 96, '초', 245, 335, ['장사', '무릉', '이릉', '장판']],
[14, '장사', '대', 4710, 97, 99, 80,100,105, '초', 255, 375, ['강릉', '시상', '계양', '무릉', '영릉']],
[15, '시상', '대', 5252, 98,100,100, 99, 96, '오월', 360, 360, ['장사', '여강', '고창', '적벽', '파양']],
[16, '위례', '대', 4926,100, 93, 80, 98,103, '동이', 620, 145, ['평양', '사비', '계림', '안평', '동황']],
[17, '계', '중', 3885, 75, 80, 60, 78, 81, '하북', 365, 35, ['진양', '역경']],
[18, '복양', '중', 4185, 80, 83, 60, 82, 80, '중원', 410, 170, ['업', '진류', '계교', '정도']],
[19, '진류', '중', 3957, 82, 80, 60, 80, 83, '중원', 365, 185, ['허창', '복양', '사수', '관도', '정도']],
[20, '여남', '중', 3831, 77, 81, 60, 84, 77, '중원', 330, 260, ['완', '수춘', '초']],
[21, '하비', '중', 4278, 85, 83, 60, 82, 78, '중원', 480, 235, ['서주', '광릉']],
[22, '서량', '중', 3874, 77, 79, 60, 83, 80, '서북', 25, 50, ['천수', '강', '저']],
[23, '하내', '중', 3736, 77, 81, 60, 81, 80, '서북', 230, 150, ['진양', '홍농', '흉노', '호관']],
[24, '한중', '중', 4027, 77, 84, 60, 80, 85, '서촉', 135, 205, ['상용', '양평', '기산']],
[25, '상용', '중', 3687, 78, 76, 60, 77, 81, '서촉', 185, 225, ['한중', '신야']],
[26, '덕양', '중', 3803, 81, 84, 60, 79, 77, '서촉', 85, 275, ['성도', '강주', '자동', '영안']],
[27, '강주', '중', 4126, 79, 80, 60, 84, 81, '서촉', 70, 310, ['성도', '덕양', '영안', '귀양', '주시']],
[28, '건녕', '중', 3765, 82, 80, 60, 86, 81, '남중', 80, 400, ['귀양', '운남', '남영']],
[29, '남해', '중', 3803, 82, 76, 60, 80, 81, '남중', 245, 480, ['교지', '상동', '대', '산월']],
[30, '계양', '중', 3955, 83, 80, 60, 81, 77, '초', 230, 400, ['장사', '영릉', '상동']],
[31, '오', '중', 4355, 77, 81, 60, 77, 76, '오월', 510, 345, ['건업', '회계', '파양', '탐라']],
[32, '평양', '중', 3982, 78, 80, 60, 83, 78, '동이', 590, 100, ['위례', '졸본']],
[33, '사비', '중', 4157, 77, 79, 60, 78, 80, '동이', 605, 205, ['위례', '계림', '탐라']],
[34, '계림', '중', 3911, 80, 74, 60, 81, 78, '동이', 655, 200, ['위례', '사비', '이도', '탐라']],
[35, '진양', '소', 3074, 56, 59, 40, 64, 59, '하북', 295, 60, ['계', '하내', '호관']],
[36, '평원', '소', 3074, 62, 65, 40, 61, 63, '하북', 440, 115, ['남피', '북해', '계교']],
[37, '북해', '소', 3146, 55, 63, 40, 63, 58, '하북', 470, 155, ['평원', '패', '동황']],
[38, '초', '소', 3286, 60, 62, 40, 62, 57, '중원', 365, 230, ['허창', '수춘', '서주', '여남', '정도']],
[39, '패', '소', 2877, 64, 58, 40, 58, 59, '중원', 430, 220, ['서주', '북해', '정도']],
[40, '천수', '소', 2985, 59, 64, 40, 60, 58, '서북', 70, 105, ['서량', '안정', '저', '적도']],
[41, '안정', '소', 2764, 57, 59, 40, 57, 62, '서북', 95, 145, ['장안', '천수', '가정']],
[42, '홍농', '소', 2748, 57, 63, 40, 58, 63, '서북', 210, 175, ['하내', '사곡', '함곡']],
[43, '하변', '소', 2785, 58, 62, 40, 60, 56, '서촉', 45, 190, ['가맹', '가정']],
[44, '자동', '소', 2870, 57, 55, 40, 60, 58, '서촉', 75, 245, ['덕양', '양평', '가맹', '면죽']],
[45, '영안', '소', 3153, 62, 59, 40, 58, 59, '서촉', 115, 295, ['덕양', '강주', '이릉']],
[46, '귀양', '소', 2746, 58, 61, 40, 61, 58, '남중', 90, 360, ['강주', '건녕', '주시']],
[47, '주시', '소', 2828, 60, 59, 40, 58, 63, '남중', 30, 345, ['강주', '귀양', '운남']],
[48, '운남', '소', 3258, 62, 60, 40, 64, 61, '남중', 30, 415, ['건녕', '주시', '남만']],
[49, '남영', '소', 2853, 59, 62, 40, 58, 57, '남중', 135, 405, ['건녕', '영릉', '남만']],
[50, '교지', '소', 3195, 58, 59, 40, 58, 59, '남중', 130, 480, ['남해', '남만']],
[51, '신야', '소', 2786, 60, 62, 40, 58, 55, '초', 250, 260, ['양양', '완', '상용']],
[52, '강하', '소', 3074, 55, 56, 40, 57, 60, '초', 315, 295, ['장판', '적벽']],
[53, '무릉', '소', 3196, 58, 63, 40, 63, 58, '초', 195, 355, ['강릉', '장사', '영릉']],
[54, '영릉', '소', 2849, 62, 58, 40, 62, 62, '초', 190, 395, ['장사', '계양', '남영', '무릉']],
[55, '상동', '소', 2767, 58, 59, 40, 62, 58, '초', 210, 435, ['남해', '계양', '고창']],
[56, '여강', '소', 2905, 56, 58, 40, 60, 55, '오월', 380, 315, ['시상', '합비', '적벽', '파양']],
[57, '회계', '소', 3005, 64, 59, 40, 62, 64, '오월', 480, 395, ['오', '산월']],
[58, '고창', '소', 2802, 57, 62, 40, 58, 63, '오월', 350, 405, ['시상', '상동', '산월']],
[59, '대', '소', 3256, 60, 62, 40, 57, 60, '오월', 450, 480, ['남해', '산월', '유구']],
[60, '안평', '소', 2937, 63, 59, 40, 59, 63, '동이', 530, 80, ['위례', '졸본', '동황', '백랑']],
[61, '졸본', '소', 2939, 55, 59, 40, 60, 58, '동이', 570, 65, ['평양', '안평', '오환']],
[62, '이도', '소', 3174, 58, 61, 40, 58, 56, '동이', 680, 260, ['계림', '왜', '탐라']],
[63, '강', '이', 2095, 40, 42, 20, 43, 40, '서북', 95, 35, ['서량', '적도']],
[64, '저', '이', 1957, 40, 42, 20, 43, 42, '서북', 25, 120, ['서량', '천수', '가정']],
[65, '흉노', '이', 2064, 40, 41, 20, 40, 38, '서북', 180, 95, ['하내', '적도']],
[66, '남만', '이', 2378, 40, 42, 20, 43, 45, '남중', 80, 455, ['운남', '남영', '교지']],
[67, '산월', '이', 2275, 40, 37, 20, 43, 38, '오월', 425, 430, ['남해', '회계', '고창', '대']],
[68, '오환', '이', 2153, 42, 37, 20, 43, 40, '동이', 610, 20, ['졸본', '백랑']],
[69, '왜', '이', 2065, 39, 37, 20, 43, 41, '동이', 680, 320, ['이도', '유구']],
[70, '호관', '관', 887, 19, 18, 20, 95, 96, '하북', 285, 140, ['업', '낙양', '하내', '진양']],
[71, '호로', '관', 1112, 22, 21, 20,103, 98, '중원', 285, 205, ['허창', '낙양', '완']],
[72, '사곡', '관', 1008, 21, 19, 20, 99,101, '서북', 240, 175, ['낙양', '홍농']],
[73, '함곡', '관', 1081, 20, 22, 20,101,102, '서북', 180, 175, ['장안', '홍농']],
[74, '사수', '관', 958, 17, 19, 20, 95, 96, '중원', 310, 185, ['허창', '낙양', '진류', '관도']],
[75, '양평', '관', 868, 19, 19, 20, 97, 96, '서촉', 90, 220, ['한중', '자동', '기산']],
[76, '가맹', '관', 855, 17, 18, 20, 96, 95, '서촉', 45, 225, ['하변', '자동']],
[77, '역경', '진', 985, 18, 19, 20, 39, 41, '하북', 410, 65, ['북평', '남피', '계']],
[78, '계교', '진', 1012, 21, 19, 20, 40, 42, '하북', 405, 135, ['업', '복양', '평원']],
[79, '동황', '진', 992, 19, 21, 20, 38, 40, '하북', 515, 145, ['위례', '북해', '안평']],
[80, '관도', '진', 1123, 22, 20, 20, 42, 43, '중원', 340, 165, ['업', '허창', '진류', '사수']],
[81, '정도', '진', 1085, 21, 21, 20, 41, 38, '중원', 400, 210, ['복양', '진류', '초', '패']],
[82, '합비', '진', 998, 20, 19, 20, 39, 41, '중원', 435, 285, ['건업', '수춘', '여강']],
[83, '광릉', '진', 1001, 20, 21, 20, 41, 40, '중원', 490, 275, ['건업', '하비']],
[84, '적도', '진', 952, 18, 17, 20, 38, 37, '서북', 130, 75, ['천수', '강', '흉노']],
[85, '가정', '진', 931, 17, 17, 20, 36, 38, '서북', 40, 160, ['안정', '하변', '저']],
[86, '기산', '진', 1005, 19, 18, 20, 41, 40, '서촉', 110, 180, ['장안', '한중', '양평']],
[87, '면죽', '관', 1093, 22, 21, 20,108, 99, '서촉', 35, 255, ['성도', '자동']],
[88, '이릉', '진', 968, 18, 19, 20, 39, 41, '초', 215, 295, ['강릉', '영안']],
[89, '장판', '진', 1032, 21, 20, 20, 40, 37, '초', 280, 315, ['양양', '강릉', '강하', '적벽']],
[90, '백랑', '진', 1052, 22, 19, 20, 38, 42, '동이', 530, 30, ['북평', '안평', '오환']],
[91, '적벽', '수', 1117, 23, 21, 20, 42, 41, '오월', 330, 325, ['시상', '강하', '여강', '장판']],
[92, '파양', '수', 1037, 20, 22, 20, 38, 38, '오월', 430, 350, ['시상', '오', '여강']],
[93, '탐라', '수', 1130, 22, 21, 20, 43, 41, '동이', 605, 260, ['오', '사비', '계림', '이도']],
[94, '유구', '수', 921, 17, 18, 20, 37, 37, '동이', 625, 435, ['대', '왜']]
];
protected static function _generate(){
if(static::$constID || static::$constName || static::$constRegion){
return;
}
$constID = [];
$constName = [];
$constCity = [];
$constRegion = [];
$nameMap = [];
foreach (static::$initCity as $rawCity) {
$nameMap[$rawCity[1]] = $rawCity[0];
}
foreach (static::$buildInit as $key=>$val){
$key2 = static::$levelMap[$key];
if(key_exists($key2, static::$buildInit)){
continue;//혹시 모를 버그 방지
}
static::$buildInit[$key2] = $val;
}
foreach(static::$initCity as $rawCity){
[
$id,
$name,
$level,
$population,
$agriculture,
$commerce,
$security,
$defence,
$wall,
$region,
$posX,
$posY,
$path
] = $rawCity;
$level = static::$levelMap[$level];
$population *= 100;
$agriculture *= 100;
$commerce *= 100;
$security *= 100;
$defence *= 100;
$wall *= 100;
$region = static::$regionMap[$region];
$newPath = [];
foreach($path as $pathName){
$pathID = $nameMap[$pathName];
$newPath[$pathID] = $pathName;
}
$city = new CityInitialDetail(
$id,
$name,
$level,
$population,
$agriculture,
$commerce,
$security,
$defence,
$wall,
$region,
$posX,
$posY,
$newPath
);
$constID[$id] = $city;
$constName[$name] = $city;
if(!key_exists($region, $constRegion)){
$constRegion[$region] = [];
}
$constRegion[$region] = $city;
}
static::$constID = $constID;
static::$constName = $constName;
static::$constRegion = $constRegion;
}
protected static $buildInitCommon = [
'rate'=>50,
'trade'=>100,
'gen1'=>0,
'gen2'=>0,
'gen3'=>0
];
protected static $buildInit = [
'수'=>[
'pop' => 5000,
'agri'=> 100,
'comm'=> 100,
'secu'=> 100,
'def' => 500,
'wall'=> 500,
],
'진'=>[
'pop' => 5000,
'agri'=> 100,
'comm'=> 100,
'secu'=> 100,
'def' => 500,
'wall'=> 500,
],
'관'=>[
'pop' => 10000,
'agri'=> 100,
'comm'=> 100,
'secu'=> 100,
'def' => 1000,
'wall'=> 1000,
],
'이'=>[
'pop' => 50000,
'agri'=> 1000,
'comm'=> 1000,
'secu'=> 1000,
'def' => 1000,
'wall'=> 1000,
],
'소'=>[
'pop' =>100000,
'agri'=> 1000,
'comm'=> 1000,
'secu'=> 1000,
'def' => 2000,
'wall'=> 2000,
],
'중'=>[
'pop' =>100000,
'agri'=> 1000,
'comm'=> 1000,
'secu'=> 1000,
'def' => 3000,
'wall'=> 3000,
],
'대'=>[
'pop' =>150000,
'agri'=> 1000,
'comm'=> 1000,
'secu'=> 1000,
'def' => 4000,
'wall'=> 4000,
],
'특'=>[
'pop' =>150000,
'agri'=> 1000,
'comm'=> 1000,
'secu'=> 1000,
'def' => 5000,
'wall'=> 5000,
]
];
protected static function test(){
static::_generate();
foreach(static::all() as $id=>$city){
foreach($city->path as $connId=>$connCityText){
$connCity = static::byID($connId);
if(!key_exists($id, $connCity->path)){
throw new \RuntimeException(sprintf('도시 연결이 올바르지 않음! %s <=> %s', $city->name, $connCity->name));
}
}
}
}
public static function build(){
static::_generate();
static::test();
$queries = array_map(function(CityInitialDetail $city){
$initValue = static::$buildInit[$city->level];
$path = join('|', array_keys($city->path));
return [
'city'=>$city->id,
'name'=>$city->name,
'level'=>$city->level,
'path'=>$path,
'pop2'=>$city->population,
'agri2'=>$city->agriculture,
'comm2'=>$city->commerce,
'secu2'=>$city->security,
'def2'=>$city->defence,
'wall2'=>$city->wall,
'region'=>$city->region
] + $initValue + static::$buildInitCommon;
}, array_values(static::$constID));
DB::db()->insert('city', $queries);
}
}
+6
View File
@@ -12,6 +12,8 @@ class CityInitialDetail{
public $defence;
public $wall;
public $region;
public $posX;
public $posY;
public $path;
public function __construct(
@@ -25,6 +27,8 @@ class CityInitialDetail{
int $defence,
int $wall,
int $region,
int $posX,
int $posY,
array $path
){
$this->id = $id;
@@ -37,6 +41,8 @@ class CityInitialDetail{
$this->defence = $defence;
$this->wall = $wall;
$this->region = $region;
$this->posX = $posX;
$this->posY = $posY;
$this->path = $path;
}
+2 -2
View File
@@ -300,7 +300,7 @@ class Diplomacy{
$chk = $this->checkValidNation();
$chk = $this->checkNonAggressionTreaty($chk);
list($result, $reason) = $chk;
[$result, $reason] = $chk;
if($result !== DiplomaticMessage::ACCEPTED){
return $chk;
}
@@ -322,7 +322,7 @@ class Diplomacy{
$chk = $this->checkValidNation();
$chk = $this->checkInWar($chk);
list($result, $reason) = $chk;
[$result, $reason] = $chk;
if($result !== DiplomaticMessage::ACCEPTED){
return $chk;
}
+2 -2
View File
@@ -37,12 +37,12 @@ class Personnel{
$this->nation = $nation;
$this->valid = true;
list(
[
$this->startYear,
$this->year,
$this->month,
$this->killturn
) = $gameStor->getValuesAsArray(['startyear', 'year', 'month', 'killturn']);
] = $gameStor->getValuesAsArray(['startyear', 'year', 'month', 'killturn']);
}
+2 -2
View File
@@ -90,13 +90,13 @@ class RaiseInvader extends \sammo\Event\Action{
if($npcEachCount < 0){
$npcEachCount =
$db->queryFirstField('SELECT count(no) from general where npc<5') / count(self::INVADER_LIST);
$db->queryFirstField('SELECT count(no) from general where npc < 9') / count(self::INVADER_LIST);
$npcEachCount /= -1 * $this->npcEachCount;
}
$specAvg = $this->specAvg;
if($specAvg < 0){
$specAvg = $db->queryFirstField('SELECT avg(sum(`leader` + `power` + `intel`)) from general where npc<5');
$specAvg = $db->queryFirstField('SELECT avg(sum(`leader` + `power` + `intel`)) from general where npc < 9');
$specAvg /= -1 * $this->specAvg;
}
+46
View File
@@ -0,0 +1,46 @@
<?php
namespace sammo\Event\Action;
class RegNeutralNPC extends \sammo\Event\Action{
private $npc;
public function __construct(
int $affinity,
string $name,
$picturePath,
int $nationID,
$locatedCity,
int $leadership,
int $power,
int $intel,
int $birth = 160,
int $death = 300,
$ego = null,
$char = '',
$text = ''
){
$this->npc = new \sammo\Scenario\NPC(
$affinity,
$name,
$picturePath,
$nationID,
$locatedCity,
$leadership,
$power,
$intel,
$birth,
$death,
$ego,
$char,
$text?:''
);
$this->npc = 6;
}
public function run($env=null){
$result = $this->npc->build($env);
return [__CLASS__, $result];
}
}
@@ -1,14 +1,16 @@
<?php
namespace sammo;
class GameConst extends GameCustomConst
class GameConstBase
{
/** @var string 버전 */
public static $title = "삼국지 모의전투 PHP HiDCHe";
/** @var string 코드 아래에 붙는 설명 코드 */
public static $banner = "KOEI의 이미지를 사용, 응용하였습니다 / 제작 : HideD(hided62@gmail.com)";
/** @var string 코드 아래에 붙는 설명 코드 */
public static $helper = "도움 주신 분들";
public static $banner = "KOEI의 이미지를 사용, 응용하였습니다 / 제작 : HideD(hided62@gmail.com) / <a href='https://sam.hided.net/wiki/hidche/credit' target='_blank' style='color:white;text-decoration: underline;'>Credit</a>";
/** @var string mapName 사용중인 지도명 */
public static $mapName = 'che';
/** @var string unitSet 사용중인 유닛셋 */
public static $unitSet = 'che';
/** @var int 내정시 최하 민심 설정*/
public static $develrate = 50;
/** @var int 능력치 상승 경험치*/
@@ -36,7 +38,7 @@ class GameConst extends GameCustomConst
/** @var int 풀징병시 훈련 1회 상승량*/
public static $atmosDelta = 30;
/** @var float 훈련시 사기 감소율*/
public static $atmosSideEffectByTraining = 0.98;
public static $atmosSideEffectByTraining = 1;
/** @var float 계략 기본 성공률*/
public static $sabotageDefaultProb = 0.25;
/** @var int 계략시 확률 가중치(수치가 클수록 변화가 적음 : (지력차/$firing + $basefiring)*/
@@ -67,6 +69,10 @@ class GameConst extends GameCustomConst
public static $exchangeFee = 0.01;
/** @var float 성인 연령 */
public static $adultAge = 14;
/** @var int 최대 계급 */
public static $maxDedLevel = 30;
/** @var int 최대 기술 레벨 */
public static $maxTechLevel = 12;
/** @var int 초기 제한시 장수 제한 */
public static $initialNationGenLimit = 10;
@@ -82,4 +88,6 @@ class GameConst extends GameCustomConst
/** @var int 최대 턴(현재는 DB상 24턴으로 고정) */
public static $maxTurn = 24;
public static $statGradeLevel = 5;
}
-161
View File
@@ -1,161 +0,0 @@
<?php
namespace sammo;
class GameUnitConst{
private function __construct(){
}
private static $constID = null;
private static $constName = null;
private static $constCity = null;
private static $constRegion = null;
/**
* @return \sammo\GameUnitDetail[]
*/
public static function all(): array{
static::_generate();
return static::$constID;
}
public static function byID(int $id): GameUnitDetail{
static::_generate();
return static::$constID[$id];
}
public static function byName(string $name): GameUnitDetail{
static::_generate();
return static::$constName[$name];
}
public static function byCity(int $city): GameUnitDetail{
static::_generate();
return static::$constCity[$city];
}
public static function byRegion(int $region): GameUnitDetail{
static::_generate();
return static::$constRegion[$region];
}
private static function _generate(){
if(static::$constID || static::$constName || static::$constCity || static::$constRegion){
return;
}
$list = [
[ 0, '보병', 100, 150, 7, 10, 9, 9, 0, 0, true, ['표준적인 보병입니다.','보병은 방어특화입니다.']],
[ 1, '청주병', 100, 200, 7, 10, 10, 11, 1, '중원', true, ['저렴하고 튼튼합니다.']],
[ 2, '수병', 150, 150, 7, 10, 11, 10, 1, '오월', true, ['저렴하고 강력합니다.']],
[ 3, '자객병', 100, 150, 7, 20, 10, 10, 2, '저', true, ['은밀하고 날쌥니다.']],
[ 4, '근위병', 150, 200, 7, 10, 12, 12, 2, '낙양', true, ['최강의 보병입니다.']],
[ 5, '등갑병', 100, 250, 7, 5, 13, 10, 1, '남중', true, ['등갑을 두른 보병입니다.']],
[10, '궁병', 100, 100, 7, 20, 10, 10, 0, 0, true, ['표준적인 궁병입니다.','궁병은 회피특화입니다.']],
[11, '궁기병', 100, 100, 8, 30, 11, 12, 1, '동이', true, ['말을 타고 잘 피합니다.']],
[12, '연노병', 150, 100, 8, 20, 12, 11, 1, '서촉', true, ['화살을 연사합니다.']],
[13, '강궁병', 150, 150, 7, 20, 13, 13, 2, '양양', true, ['강건한 궁병입니다.']],
[14, '석궁병', 200, 100, 7, 20, 13, 13, 2, '건업', true, ['강력한 화살을 쏩니다.']],
[20, '기병', 150, 100, 7, 5, 11, 11, 0, 0, true, ['표준적인 기병입니다.','기병은 공격특화입니다.']],
[21, '백마병', 200, 100, 7, 5, 12, 13, 1, '하북', true, ['백마의 위용을 보여줍니다.']],
[22, '중장기병', 150, 150, 7, 5, 13, 12, 1, '서북', true, ['갑주를 두른 기병입니다.']],
[23, '돌격기병', 200, 100, 8, 5, 13, 11, 2,'흉노', true, ['저돌적으로 공격합니다.']],
[24, '철기병', 100, 200, 7, 5, 11, 13, 2, '강', true, ['철갑을 두른 기병입니다.']],
[25, '수렵기병', 150, 100, 8, 15, 12, 12, 2, '산월', true, ['날쎄고 빠른 기병입니다.']],
[26, '맹수병', 250, 200, 6, 0, 16, 16, 2, '남만', true, ['어느 누구보다 강력합니다.']],
[27, '호표기병', 200, 150, 7, 5, 14, 14, 2, '허창', true, ['정예 기병입니다.']],
[30, '귀병', 80, 80, 7, 5, 9, 9, 0, 0, true, ['계략을 사용하는 병종입니다.']],
[31, '신귀병', 80, 80, 7, 20, 10, 10, 1,'초', true, ['신출귀몰한 귀병입니다.']],
[32, '백귀병', 80, 130, 7, 5, 9, 11, 2, '오환', true, ['저렴하고 튼튼합니다.']],
[33, '흑귀병', 130, 80, 7, 5, 11, 9, 2, '왜', true, ['저렴하고 강력합니다.']],
[34, '악귀병', 130, 130, 7, 0, 12, 12, 2, '장안', true, ['백병전에도 능숙합니다.']],
[35, '남귀병', 60, 60, 7, 10, 8, 8, 0, 1000, false, ['전투를 포기하고 계략에 몰두합니다.']],
[36, '황귀병', 110, 110, 7, 0, 13, 10, 2, '낙양', true, ['고도로 훈련된 귀병입니다.']],
[37, '천귀병', 80, 130, 7, 15, 11, 12, 2, '성도', true, ['갑주를 두른 귀병입니다.']],
[38, '마귀병', 130, 80, 7, 15, 12, 11, 2, '업', true, ['날카로운 무기를 가진 귀병입니다.']],
[40, '정란', 100, 100, 6, 0, 15, 5, 0, 0, false, ['높은 구조물 위에서 공격합니다.']],
[41, '충차', 150, 100, 6, 0, 20, 5, 0, 1000, false, ['엄청난 위력으로 성벽을 부수어버립니다.']],
[42, '벽력거', 200, 100, 6, 0, 25, 5, 2, '업', true, ['상대에게 돌덩이를 날립니다.']],
[43, '목우', 50, 200, 5, 0, 30, 5, 2, '성도', true, ['상대를 저지하는 특수병기입니다.']]
];
$constID = [];
$constName = [];
$constCity = [];
$constRegion = [];
foreach($list as $rawUnit){
list(
$id,
$name,
$attack,
$defence,
$speed,
$avoid,
$cost,
$rice,
$recruitType,
$recruitCondition,
$recruitFirst,
$info
) = $rawUnit;
//0인 경우는 기술치이다.
if(!$recruitFirst){
$info[] = "일정 시간이 지나야 사용 가능";
}
if($recruitType == 1){
$info[] = "{$recruitCondition}지역 소유시 가능";
$recruitCondition = CityConst::$regionMap[$recruitCondition];
}
else if($recruitType == 2){
$info[] = "{$recruitCondition} 소유시 가능";
$recruitCondition = CityConst::byName($recruitCondition)->id;
}
$unit = new GameUnitDetail(
$id,
$name,
$attack,
$defence,
$speed,
$avoid,
$cost,
$rice,
$recruitType,
$recruitCondition,
$recruitFirst,
$info
);
$constID[$id] = $unit;
$constName[$name] = $unit;
if($recruitType == 1){
if(!key_exists($recruitCondition, $constRegion)){
$constRegion[$recruitCondition] = [];
}
$constRegion[$recruitCondition][] = $unit;
}
if($recruitType == 2){
if(!key_exists($recruitCondition, $constCity)){
$constCity[$recruitCondition] = [];
}
$constCity[$recruitCondition][] = $unit;
}
}
static::$constID = $constID;
static::$constName = $constName;
static::$constCity = $constCity;
static::$constRegion = $constRegion;
}
}
+459
View File
@@ -0,0 +1,459 @@
<?php
namespace sammo;
class GameUnitConstBase{
protected function __construct(){
}
const T_CASTLE = -1;
const T_MISC = -2;
const T_FOOTMAN = 0;
const T_ARCHER = 1;
const T_CAVALRY = 2;
const T_WIZARD = 3;
const T_SIEGE = 4;
const DEFAULT_CREWTYPE = 0;
protected static $constID = null;
protected static $constName = null;
protected static $constCity = null;
protected static $constRegion = null;
protected static $constType = null;
protected static $typeData = [
self::T_FOOTMAN => '보병',
self::T_ARCHER => '궁병',
self::T_CAVALRY => '기병',
self::T_WIZARD => '귀병',
self::T_SIEGE => '차병',
];
protected static $_buildData = [
[
-1, self::T_CASTLE, '성벽',
100, 100, 7, 0, 0, 99, 9,
999999, null, null, 999999,
[],//성벽은 공격할 수 없다.
[],
['성벽입니다.','생성할 수 없습니다.']
],
[
0, self::T_FOOTMAN, '보병',
100, 150, 7, 10, 0, 9, 9,
0, null, null, 0,
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['표준적인 보병입니다.','보병은 방어특화입니다.']
],
[
1, self::T_FOOTMAN, '청주병',
100, 200, 7, 10, 0, 10, 11,
1000, null, ['중원'], 0,
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['저렴하고 튼튼합니다.']
],
[
2, self::T_FOOTMAN, '수병',
150, 150, 7, 10, 0, 11, 10,
1000, null, ['오월'], 0,
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['저렴하고 강력합니다.']
],
[
3, self::T_FOOTMAN, '자객병',
100, 150, 7, 20, 0, 10, 10,
2000, ['저'], null, 0,
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['은밀하고 날쌥니다.']
],
[
4, self::T_FOOTMAN, '근위병',
150, 200, 7, 10, 0, 12, 12,
3000, ['낙양'], null, 0,
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['최강의 보병입니다.']
],
[
5, self::T_FOOTMAN, '등갑병',
100, 250, 7, 5, 0, 13, 10,
1000, null, ['남중'], 0,
[self::T_ARCHER=>1.2, self::T_CAVALRY=>0.8, self::T_SIEGE=>1.2],
[self::T_ARCHER=>0.8, self::T_CAVALRY=>1.2, self::T_SIEGE=>0.8],
['등갑을 두른 보병입니다.']
],
[
10, self::T_ARCHER, '궁병',
100, 100, 7, 20, 0, 10, 10,
0, null, null, 0,
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
['표준적인 궁병입니다.','궁병은 회피특화입니다.']
],
[
11, self::T_ARCHER, '궁기병',
100, 100, 8, 30, 0, 11, 12,
1000, null, ['동이'], 0,
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
['말을 타고 잘 피합니다.']
],
[
12, self::T_ARCHER, '연노병',
150, 100, 8, 20, 0, 12, 11,
1000, null, ['서촉'], 0,
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
['화살을 연사합니다.']
],
[
13, self::T_ARCHER, '강궁병',
150, 150, 7, 20, 0, 13, 13,
3000, ['양양'], null, 0,
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
['강건한 궁병입니다.']
],
[
14, self::T_ARCHER, '석궁병',
200, 100, 7, 20, 0, 13, 13,
3000, ['건업'], null, 0,
[self::T_CAVALRY=>1.2, self::T_FOOTMAN=>0.8, self::T_SIEGE=>1.2],
[self::T_CAVALRY=>0.8, self::T_FOOTMAN=>1.2, self::T_SIEGE=>0.8],
['강력한 화살을 쏩니다.']
],
[
20, self::T_CAVALRY, '기병',
150, 100, 7, 5, 0, 11, 11,
0, null, null, 0,
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['표준적인 기병입니다.','기병은 공격특화입니다.']
],
[
21, self::T_CAVALRY, '백마병',
200, 100, 7, 5, 0, 12, 13,
1000, null, ['하북'], 0,
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['백마의 위용을 보여줍니다.']
],
[
22, self::T_CAVALRY, '중장기병',
150, 150, 7, 5, 0, 13, 12,
1000, null, ['서북'], 0,
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['갑주를 두른 기병입니다.']
],
[
23, self::T_CAVALRY, '돌격기병',
200, 100, 8, 5, 0, 13, 11,
2000, ['흉노'], null, 0,
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['저돌적으로 공격합니다.']
],
[
24, self::T_CAVALRY, '철기병',
100, 200, 7, 5, 0, 11, 13,
2000, ['강'], null, 0,
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['철갑을 두른 기병입니다.']],
[
25, self::T_CAVALRY, '수렵기병',
150, 100, 8, 15, 0, 12, 12,
2000, ['산월'], null, 0,
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['날쎄고 빠른 기병입니다.']
],
[
26, self::T_CAVALRY, '맹수병',
250, 200, 6, 0, 0, 16, 16,
2000, ['남만'], null, 0,
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['어느 누구보다 강력합니다.']
],
[
27, self::T_CAVALRY, '호표기병',
200, 150, 7, 5, 0, 14, 14,
3000, ['허창'], null, 0,
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>0.8, self::T_SIEGE=>1.2],
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>1.2, self::T_SIEGE=>0.8],
['정예 기병입니다.']
],
[
30, self::T_WIZARD, '귀병',
80, 80, 7, 5, 0.5, 9, 9,
0, null, null, 0,
[self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8],
['계략을 사용하는 병종입니다.']
],
[
31, self::T_WIZARD, '신귀병',
80, 80, 7, 20, 0.6, 10, 10,
1000, null, ['초'], 0,
[self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8],
['신출귀몰한 귀병입니다.']
],
[
32, self::T_WIZARD, '백귀병',
80, 130, 7, 5, 0.6, 9, 11,
2000, ['오환'], null, 0,
[self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8],
['저렴하고 튼튼합니다.']
],
[
33, self::T_WIZARD, '흑귀병',
130, 80, 7, 5, 0.6, 11, 9,
2000, ['왜'], null, 0,
[self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8],
['저렴하고 강력합니다.']
],
[
34, self::T_WIZARD, '악귀병',
130, 130, 7, 0, 0.6, 12, 12,
3000, ['장안'], null, 0,
[self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8],
['백병전에도 능숙합니다.']
],
[
35, self::T_WIZARD, '남귀병',
60, 60, 7, 10, 0.8, 8, 8,
1000, null, null, 0,
[self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8],
['전투를 포기하고 계략에 몰두합니다.']
],
[
36, self::T_WIZARD, '황귀병',
110, 110, 7, 0, 0.8, 13, 10,
3000, ['낙양'], null, 0,
[self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8],
['고도로 훈련된 귀병입니다.']
],
[
37, self::T_WIZARD, '천귀병',
80, 130, 7, 15, 0.6, 11, 12,
3000, ['성도'], null, 0,
[self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8],
['갑주를 두른 귀병입니다.']
],
[
38, self::T_WIZARD, '마귀병',
130, 80, 7, 15, 0.6, 12, 11,
3000, ['업'], null, 0,
[self::T_SIEGE=>1.2],
[self::T_SIEGE=>0.8],
['날카로운 무기를 가진 귀병입니다.']
],
[
40, self::T_SIEGE, '정란',
100, 100, 6, 0, 0, 15, 5,
0, null, null, 3,
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>1.8],
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
['높은 구조물 위에서 공격합니다.']
],
[
41, self::T_SIEGE, '충차',
150, 100, 6, 0, 0, 20, 5,
1000, null, null, 3,
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>2.4],
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
['엄청난 위력으로 성벽을 부수어버립니다.']
],
[
42, self::T_SIEGE, '벽력거',
200, 100, 6, 0, 0, 25, 5,
3000, ['업'], null, 0,
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8, self::T_CASTLE=>1.8],
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
['상대에게 돌덩이를 날립니다.']
],
[
43, self::T_SIEGE, '목우',
50, 200, 5, 0, 0, 30, 5,
3000, ['성도'], null, 0,
[self::T_FOOTMAN=>0.8, self::T_ARCHER=>0.8, self::T_CAVALRY=>0.8, self::T_WIZARD=>0.8],
[self::T_FOOTMAN=>1.2, self::T_ARCHER=>1.2, self::T_CAVALRY=>1.2, self::T_WIZARD=>1.2],
['상대를 저지하는 특수병기입니다.']
]
];
/**
* @return \sammo\GameUnitDetail[]
*/
public static function all(): array{
static::_generate();
return static::$constID;
}
public static function allType(): array{
return static::$typeData;
}
public static function byID(int $id): ?GameUnitDetail{
static::_generate();
return static::$constID[$id]??null;
}
public static function byName(string $name): ?GameUnitDetail{
static::_generate();
return static::$constName[$name]??null;
}
public static function byCity(int $city): array{
static::_generate();
return static::$constCity[$city]??[];
}
public static function byRegion(int $region): array{
static::_generate();
return static::$constRegion[$region]??[];
}
public static function byType(int $type): array{
static::_generate();
if(!key_exists($type, static::$constType)){
return [];
}
return static::$constType[$type];
}
protected static function _generate(){
if(static::$constID || static::$constName || static::$constCity || static::$constRegion || static::$constType){
return;
}
$constID = [];
$constName = [];
$constCity = [];
$constRegion = [];
$constType = [];
foreach(static::$_buildData as $rawUnit){
[
$id,
$armType,
$name,
$attack,
$defence,
$speed,
$avoid,
$magicCoef,
$cost,
$rice,
$reqTech,
$reqCities,
$reqRegions,
$reqYear,
$attackCoef,
$defenceCoef,
$info
] = $rawUnit;
if($reqYear > 0){
$info[] = "{$reqYear}년 경과 후 사용 가능";
}
if($reqTech > 0){
$info[] = "기술력 {$reqTech} 이상 필요";
}
if($reqCities !== null){
$reqCities = array_map(function($reqCity) use (&$info){
$info[] = "{$reqCity} 소유시 가능";
return CityConst::byName($reqCity)->id;
}, $reqCities);
}
if($reqRegions !== null){
$reqRegions = array_map(function($reqRegion) use (&$info){
$info[] = "{$reqRegion} 지역 소유시 가능";
return CityConst::$regionMap[$reqRegion];
}, $reqRegions);
}
$unit = new GameUnitDetail(
$id,
$armType,
$name,
$attack,
$defence,
$speed,
$avoid,
$magicCoef,
$cost,
$rice,
$reqTech,
$reqCities,
$reqRegions,
$reqYear,
$attackCoef,
$defenceCoef,
$info
);
$constID[$id] = $unit;
$constName[$name] = $unit;
if(!key_exists($armType, $constType)){
$constType[$armType] = [];
}
$constType[$armType][] = $unit;
if($unit->reqCities){
foreach($unit->reqCities as $reqCity){
if(!key_exists($reqCity, $constCity)){
$constCity[$reqCity] = [];
}
$constCity[$reqCity][] = $unit;
}
}
if($unit->reqRegions){
foreach($unit->reqRegions as $reqRegion){
if(!key_exists($reqRegion, $constRegion)){
$constRegion[$reqRegion] = [];
}
$constRegion[$reqRegion][] = $unit;
}
}
}
static::$constID = $constID;
static::$constName = $constName;
static::$constCity = $constCity;
static::$constRegion = $constRegion;
static::$constType = $constType;
}
}
+151 -34
View File
@@ -3,80 +3,197 @@ namespace sammo;
class GameUnitDetail{
public $id;
public $armType;
public $name;
public $attack;
public $defence;
public $speed;
public $avoid;
public $magicCoef;
public $cost;
public $rice;
public $recruitType;
public $recruitCondition;
public $recruitFirst;
public $reqTech;
public $reqCities;
public $reqRegions;
public $reqYear;
public $attackCoef;
public $defenceCoef;
public $info;
public function __construct(
int $id,
int $armType,
string $name,
int $attack,
int $defence,
int $speed,
int $avoid,
float $magicCoef,
int $cost,
int $rice,
int $recruitType,
int $recruitCondition,
bool $recruitFirst,
int $reqTech,
?array $reqCities,
?array $reqRegions,
int $reqYear,
array $attackCoef,
array $defenceCoef,
array $info
){
$this->id = $id;
$this->name = $name;
$this->armType = $armType;
$this->attack = $attack;
$this->defence = $defence;
$this->speed = $speed;
$this->avoid = $avoid;
$this->magicCoef = $magicCoef;
$this->cost = $cost;
$this->rice = $rice;
$this->recruitType = $recruitType;
$this->recruitCondition = $recruitCondition;
$this->recruitFirst = $recruitFirst;
$this->reqTech = $reqTech;
$this->reqCities = $reqCities;
$this->reqRegions = $reqRegions;
$this->reqYear = $reqYear;
$this->attackCoef = $attackCoef;
$this->defenceCoef = $defenceCoef;
$this->info = $info;
}
public function getShortName():string{
return StringUtil::subStringForWidth($this->name, 0, 4);
}
public function costWithTech(int $tech, int $crew=100):float{
return $this->cost * getTechCost($tech) * $crew / 100;
}
public function getAttackCoef($armType):float{
if($armType instanceof GameUnitDetail){
$armType = $armType->armType;
}
assert(is_numeric($armType), '$armType should be int or GameUnitDetail');
return $this->attackCoef[$armType]??1;
}
public function getDefenceCoef($armType):float{
if($armType instanceof GameUnitDetail){
$armType = $armType->armType;
}
assert(is_numeric($armType), '$armType should be int or GameUnitDetail');
return $this->defenceCoef[$armType]??1;
}
public function getComputedAttack(array $general, int $tech){
if($this->armType == GameUnitConst::T_CASTLE){
assert(isset($general['def']) && isset($general['wall']), '도시 정보가 입력되어야 함');
return ($general['def'] + $general['wall']*9) / 500 + 200;
}
if($this->armType == GameUnitConst::T_WIZARD){
$ratio = getGeneralIntel($general, true, true, true)*2 - 40;
}
else if($this->armType == GameUnitConst::T_SIEGE){
$ratio = getGeneralLeadership($general, true, true, true)*2 - 40;
}
else if($this->armType == GameUnitConst::T_MISC){
$ratio = getGeneralIntel($general, true, true, true) +
getGeneralLeadership($general, true, true, true) +
getGeneralPower($general, true, true, true);
$ratio = $ratio*2/3 - 40;
}
else{
$ratio = getGeneralPower($general, true, true, true)*2 - 40;
}
if($ratio < 10){
$ratio = 10;
}
if($ratio > 100){
$ratio = 50 + $ratio/2;
}
$att = $this->attack + getTechAbil($tech);
return $att * $ratio / 100;
}
public function getComputedDefence(array $general, int $tech){
if($this->armType == GameUnitConst::T_CASTLE){
assert(isset($general['def']) && isset($general['wall']), '도시 정보가 입력되어야 함');
return ($general['def'] + $general['wall']*9) / 500 + 200;
}
$def = $this->defence + getTechAbil($tech);
$crew = ($general['crew'] / (7000 / 30)) + 70;
return $def * $crew / 100;
}
public function getCriticalRatio(array $general){
if($this->armType == GameUnitConst::T_CASTLE){
//성벽은 필살을 사용하지 않는다.
return 0;
}
// 무장 무력 : 65 5%, 70 10%, 75 15%, 80 20%
// 지장 지력 : 65 5%, 70 8%, 75 10%, 80 13%
//충차장 통솔: 65 5%, 70 8%, 75 10%, 80 13%
if($this->armType == GameUnitConst::T_WIZARD){
$mainstat = getGeneralIntel($general, false, true, true, false);
$coef = 0.4;
}
else if($this->armType == GameUnitConst::T_SIEGE){
$mainstat = getGeneralLeadership($general, false, true, true, false);
$coef = 0.4;
}
else if($this->armType == GameUnitConst::T_MISC){
$mainstat = getGeneralIntel($general, false, true, true, false) +
getGeneralLeadership($general, false, true, true, false) +
getGeneralPower($general, false, true, true, false);
$mainstat /= 3;
$coef = 0.4;
}
else{
$mainstat = getGeneralPower($general, false, true, true, false);
$coef = 0.5;
}
$ratio = max($mainstat - 65, 0);
$ratio *= $coef;
return min(50, $ratio) / 100;
}
public function isValid($ownCities, $ownRegions, $relativeYear, $tech){
if($relativeYear < 3 && !$this->recruitFirst){
//음수 없음
$relativeYear = max(0, $relativeYear);
if($relativeYear < $this->reqYear){
return false;
}
if($this->recruitType == 0){
if($tech < $this->recruitCondition){
if($tech < $this->reqTech){
return false;
}
if($this->reqCities !== null){
$valid = false;
foreach($this->reqCities as $reqCity){
if(\key_exists($reqCity, $ownCities)){
$valid = true;
break;
}
}
if(!$valid){
return false;
}
}
if($this->recruitType == 1){
if(!key_exists($this->recruitCondition, $ownRegions)){
return false;
}
if ($tech < 1000) {
return false;
}
}
if($this->recruitType == 2){
$cityLevel = CityConst::byID($this->recruitCondition)->level;
if(!key_exists($this->recruitCondition, $ownCities)){
return false;
}
if($cityLevel == CityConst::$levelMap['특']){
if ($tech < 3000) {
return false;
if($this->reqRegions !== null){
$valid = false;
foreach($this->reqRegions as $reqRegion){
if(\key_exists($reqRegion, $ownRegions)){
$valid = true;
break;
}
}
else{ //if($cityLevel == '이')
if ($tech < 2000) {
return false;
}
if(!$valid){
return false;
}
}
+25 -3
View File
@@ -143,6 +143,24 @@ class ResetHelper{
]);
CityConst::build();
$cityPositions = [];
foreach(CityConst::all() as $city){
$cityPositions[$city->id] = [
$city->name,
$city->posX,
$city->posY
];
}
Util::generateFileUsingSimpleTemplate(
__dir__.'/../templates/base_map.orig.js',
__dir__.'/../d_shared/base_map.js',
[
'cityPosition'=>Json::encode($cityPositions),
'regionMap'=>Json::encode(CityConst::$regionMap),
'levelMap'=>Json::encode(CityConst::$levelMap),
],
true
);
$turntime = date('Y-m-d H:i:s');
@@ -154,7 +172,7 @@ class ResetHelper{
$year = $startyear;
} else {
// 현재 시간과 동기화
list($starttime, $yearPulled, $month) = cutDay($turntime, $turnterm);
[$starttime, $yearPulled, $month] = cutDay($turntime, $turnterm);
if($yearPulled){
$year = $startyear-1;
}
@@ -166,7 +184,7 @@ class ResetHelper{
$killturn = 4800 / $turnterm;
if($npcmode == 1) { $killturn = intdiv($killturn, 3); }
$develcost = ($year - $startyear + 10) * 2;
$env = [
'scenario'=>$scenario,
@@ -175,12 +193,14 @@ class ResetHelper{
'startyear'=>$startyear,
'year'=> $year,
'month'=> $month,
'map_theme' => $scenarioObj->getMapTheme(),
'msg'=>'공지사항',//TODO:공지사항
'maxgeneral'=>GameConst::$defaultMaxGeneral,
'maxnation'=>GameConst::$defaultMaxNation,
'conlimit'=>300,
'gold_rate'=>100,
'rice_rate'=>100,
'develcost'=>$develcost,
'turntime'=>$turntime,
'starttime'=>$starttime,
'turnterm'=>$turnterm,
@@ -200,7 +220,8 @@ class ResetHelper{
'picture'=>$admin['picture'],
'imgsvr'=>$admin['imgsvr'],
'turntime'=>$turntime,
'killturn'=>9999
'killturn'=>9999,
'crewtype'=>GameUnitConst::DEFAULT_CREWTYPE
]);
}
@@ -212,6 +233,7 @@ class ResetHelper{
'server_id'=>$serverID,
'date'=>$turntime,
'winner_nation'=>null,
'map'=>$scenarioObj->getMapTheme(),
'scenario'=>$scenario,
'scenario_name'=>$scenarioObj->getTitle(),
'env'=>Json::encode($env)
+118 -12
View File
@@ -22,6 +22,7 @@ class Scenario{
private $generals;
private $generalsEx;
private $generalsNeutral;
private $tmpGeneralQueue = [];
@@ -151,6 +152,50 @@ class Scenario{
}, Util::array_get($data['general_ex'], []));
$this->generalsNeutral = array_map(function($rawGeneral){
while(count($rawGeneral) < 14){
$rawGeneral[] = null;
}
list(
$affinity, $name, $picturePath, $nationName, $locatedCity,
$leadership, $power, $intel, $level, $birth, $death, $ego,
$char, $text
) = $rawGeneral;
if(key_exists($nationName, $this->nationsInv)){
$nationID = $this->nationsInv[$nationName]->id;;
}
else if(key_exists($nationName, $this->nations)){
$nationID = (int)$nationName;
}
else{
$nationID = 0;
}
$this->tmpGeneralQueue[$name] = $rawGeneral;
$npc = new Scenario\NPC(
$affinity,
$name,
$picturePath,
$nationID,
$locatedCity,
$leadership,
$power,
$intel,
$level,
$birth,
$death,
$ego,
$char,
$text
);
$npc->npc = 6;
return $npc;
}, Util::array_get($data['general_neutral'], []));
$this->initialEvents = array_map(function($rawEvent){
$cond = $rawEvent[0];
$action = array_slice($rawEvent, 1);
@@ -182,15 +227,20 @@ class Scenario{
$default = Json::decode(file_get_contents($defaultPath));
$stat = [
'statTotal'=>$this->data['stat']['total']??$default['stat']['total'],
'statMin'=>$this->data['stat']['min']??$default['stat']['min'],
'statMax'=>$this->data['stat']['max']??$default['stat']['max'],
'statNPCMax'=>$this->data['stat']['npcMax']??$default['stat']['npcMax'],
'statChiefMin'=>$this->data['stat']['chiefMin']??$default['stat']['chiefMin'],
'defaultStatTotal'=>$this->data['stat']['total']??$default['stat']['total'],
'defaultStatMin'=>$this->data['stat']['min']??$default['stat']['min'],
'defaultStatMax'=>$this->data['stat']['max']??$default['stat']['max'],
'defaultStatNPCMax'=>$this->data['stat']['npcMax']??$default['stat']['npcMax'],
'chiefStatMin'=>$this->data['stat']['chiefMin']??$default['stat']['chiefMin'],
];
$this->gameConf = array_merge($stat);
$this->gameConf = array_merge($stat, $this->data['map']??[], $this->data['const']??[]);
$this->iconPath = $this->data['iconPath']??$default['iconPath'];
$this->gameConf['mapName'] = $this->gameConf['mapName']??'che';
$this->gameConf['unitSet'] = $this->gameConf['unitSet']??'che';
return $this->gameConf;
}
@@ -242,10 +292,23 @@ class Scenario{
return $this->generalsEx;
}
public function getNPCneutral(){
$this->initFull();
return $this->generalsNeutral;
}
public function getNation(){
$this->initFull();
return $this->nations;
}
public function getMapTheme(){
return $this->gameConf['mapName'];
}
public function getUnitSet(){
return $this->gameConf['unitSet'];
}
public function getScenarioBrief(){
$this->initFull();
@@ -253,6 +316,7 @@ class Scenario{
$nations = [];
$nationGeneralCnt = [];
$nationGeneralExCnt = [];
$nationGeneralNeutralCnt = [];
foreach($this->generals as $general){
$nationID = $general->nationID;
@@ -274,15 +338,27 @@ class Scenario{
}
}
foreach($this->generalsNeutral as $general){
$nationID = $general->nationID;
if(!key_exists($nationID, $nationGeneralNeutralCnt)){
$nationGeneralNeutralCnt[$nationID] = 1;
}
else{
$nationGeneralNeutralCnt[$nationID] += 1;
}
}
return [
'year'=>$this->getYear(),
'title'=>$this->getTitle(),
'npc_cnt'=>count($this->getNPC()),
'npcEx_cnt'=>count($this->getNPCex()),
'npcNeutral_cnt'=>count($this->getNPCneutral()),
'nation'=>array_map(function($nation) use ($nationGeneralCnt, $nationGeneralExCnt){
$brief = $nation->getBrief();
$brief['generals'] = Util::array_get($nationGeneralCnt[$nation->getID()], 0);
$brief['generalsEx'] = Util::array_get($nationGeneralExCnt[$nation->getID()], 0);
$brief['generalsNeutral'] = Util::array_get($nationGeneralNeutralCnt[$nation->getID()], 0);
return $brief;
},$this->getNation())
@@ -337,6 +413,23 @@ class Scenario{
$remainGenerals[$birth][] = array_merge(['RegNPC'], $rawGeneral);
}
}
foreach($this->generalsNeutral as $general){
if($general->build($env)){
if($general->nationID){
$this->nations[$general->nationID]->addGeneral($general);
}
continue;
}
$rawGeneral = $this->tmpGeneralQueue[$general->name];
$birth = $general->birth;
if(!key_exists($birth, $remainGenerals)){
$remainGenerals[$birth] = [];
}
$remainGenerals[$birth][] = array_merge(['RegNeutralNPC'], $rawGeneral);
}
return $remainGenerals;
}
@@ -357,12 +450,25 @@ class Scenario{
public function buildConf(){
$path = __dir__.'/../d_setting';
Util::generateFileUsingSimpleTemplate(
$path.'/GameCustomConst.orig.php',
$path.'/GameCustomConst.php',
$this->gameConf,
true
);
$mapPath = __dir__.'/../scenario/map';
$unitPath = __dir__.'/../scenario/unit';
$mapName = $this->gameConf['mapName'];
$unitSet = $this->gameConf['unitSet'];
if(!file_exists("$mapPath/$mapName.php")){
throw new \RuntimeException('맵 파일이 올바르게 지정되지 않음! : '.$mapName);
}
if(!file_exists("$unitPath/$unitSet.php")){
throw new \RuntimeException('유닛 파일이 올바르게 지정되지 않음! : '.$unitSet);
}
Util::generatePHPClassFile($path.'/GameConst.php', $this->gameConf, 'GameConstBase', 'sammo');
copy("$mapPath/$mapName.php", $path.'/CityConst.php');
copy("$unitPath/$unitSet.php", $path.'/GameUnitConst.php');
}
public function build($env=[]){
+5 -3
View File
@@ -4,6 +4,7 @@ use \sammo\Util;
use \sammo\JosaUtil;
use \sammo\DB;
use \sammo\CityHelper;
use \sammo\GameUnitConst;
class NPC{
@@ -21,6 +22,7 @@ class NPC{
public $ego;
public $charDomestic = 0;
public $charWar = 0;
public $npc = 2;
public $text;
//[ 1, "헌제",1002, 1, null, 17, 13, 61, 0, 170, 250, "안전", null, "산 넘어 산이로구나..."],
@@ -210,8 +212,8 @@ class NPC{
$db->insert('general',[
'npcid'=>$npcID,
'npc'=>2,
'npc_org'=>2,
'npc'=>$this->npc,
'npc_org'=>$this->npc,
'affinity'=>$affinity,
'name'=>$name,
'picture'=>$picturePath,
@@ -226,7 +228,7 @@ class NPC{
'gold'=>1000,
'rice'=>1000,
'crew'=>0,
'crewtype'=>0,
'crewtype'=>GameUnitConst::DEFAULT_CREWTYPE,
'train'=>0,
'atmos'=>0,
'weap'=>0,
+400
View File
@@ -0,0 +1,400 @@
<?php
namespace sammo;
class WarUnit{
protected $raw;
protected $rawNation;
protected $logger;
protected $crewType;
protected $killedCurr = 0;
protected $killed = 0;
protected $deadCurr = 0;
protected $dead = 0;
protected $isAttacker = false;
protected $updatedVar = [];
protected $currPhase = 0;
protected $prePhase = 0;
protected $atmosBonus = 0;
protected $trainBonus = 0;
protected $oppose;
protected $warPower;
protected $warPowerMultiply = 1.0;
protected $activatedSkill = [];
protected $isFinished = false;
private function __construct(){
}
function getRaw():array{
return $this->raw;
}
function getRawNation():array{
return $this->rawNation;
}
function getVar(string $key){
return $this->raw[$key];
}
function updateVar(string $key, $value){
if($this->raw[$key] === $value){
return;
}
$this->raw[$key] = $value;
$this->updatedVar[$key] = true;
}
function updateVarWithLimit(string $key, $value, $min = null, $max = null){
if($min !== null && $value < $min){
$value = $min;
}
if($max !== null && $value > $max){
$value = $max;
}
$this->updateVar($key, $value);
}
function increaseVar(string $key, $value)
{
if($value === 0){
return;
}
$this->raw[$key] += $value;
$this->updatedVar[$key] = true;
}
function increaseVarWithLimit(string $key, $value, $min = null, $max = null){
$targetValue = $this->raw[$key] + $value;
if($min !== null && $targetValue < $min){
$targetValue = $min;
}
if($max !== null && $targetValue > $max){
$targetValue = $max;
}
$this->updateVar($key, $targetValue);
}
function multiplyVar(string $key, $value)
{
if($value === 1){
return;
}
$this->raw[$key] *= $value;
$this->updatedVar[$key] = true;
}
function multiplyVarWithLimit(string $key, $value, $min = null, $max = null){
$targetValue = $this->raw[$key] * $value;
if($min !== null && $targetValue < $min){
$targetValue = $min;
}
if($max !== null && $targetValue > $max){
$targetValue = $max;
}
$this->updateVar($key, $targetValue);
}
function getNationVar(string $key){
return $this->rawNation[$key];
}
function getPhase():int{
return $this->currPhase;
}
function getRealPhase():int{
return $this->prePhase + $this->currPhase;
}
function getName():string{
return 'EMPTY';
}
function isAttacker():bool{
return $this->isAttacker;
}
function getCrewType():GameUnitDetail{
return $this->crewType;
}
function getCrewTypeName():string{
return $this->getCrewType()->name;
}
function getCrewTypeShortName():string{
return $this->getCrewType()->getShortName();
}
function getLogger():ActionLogger{
return $this->logger;
}
function getKilled():int{
return $this->killed;
}
function getDead():int{
return $this->dead;
}
function getKilledCurrentBattle():int{
return $this->killedCurr;
}
function getDeadCurrentBattle():int{
return $this->deadCurr;
}
function getSpecialDomestic():int{
return 0;
}
function getSpecialWar():int{
return 0;
}
function getItem():int{
return 0;
}
function getMaxPhase():int{
return $this->getCrewType()->speed;
}
function setPrePhase(int $phase){
$this->prePhase = $phase;
}
function addPhase(){
$this->currPhase += 1;
}
function setOppose(?WarUnit $oppose){
$this->oppose = $oppose;
$this->killedCurr = 0;
$this->deadCurr = 0;
$this->activatedSkill = [];
}
function getOppose():?WarUnit{
return $this->oppose;
}
function getWarPower(){
return $this->warPower * $this->warPowerMultiply;
}
function getRawWarPower(){
return $this->warPower;
}
function getWarPowerMultiply(){
return $this->warPowerMultiply;
}
function setWarPowerMultiply($multiply = 1.0){
$this->warPowerMultiply = $multiply;
}
function multiplyWarPowerMultiply($multiply){
$this->warPowerMultiply *= $multiply;
}
function computeWarPower(){
$oppose = $this->oppose;
$myAtt = $this->getCrewType()->getComputedAttack($this->getRaw(), $this->getNationVar('tech'));
$opDef = $oppose->getCrewType()->getComputedDefence($oppose->getRaw(), $oppose->getNationVar('tech'));
// 감소할 병사 수
$warPower = GameConst::$armperphase + $myAtt - $opDef;
$opposeWarPowerMultiply = 1.0;
if($warPower < 100){
//최소 전투력 50 보장
$warPower = max(0, $warPower);
$warPower = ($warPower + 100) / 2;
$warPower = rand($warPower, 100);
}
$warPower *= CharAtmos(
$this->getComputedAtmos(),
$this->getCharacter()
);
$warPower /= CharTrain(
$oppose->getComputedTrain(),
$oppose->getCharacter()
);
if($this instanceof WarUnitGeneral){
$genDexAtt = getGenDex($this->getRaw(), $this->getCrewType()->id);
}
else{
$genDexAtt = ($this->cityRate - 60) * 7200;
}
if($this instanceof WarUnitGeneral){
$oppDexDef = getGenDex($oppose->getRaw(), $this->getCrewType()->id);
}
else{
$oppDexDef = ($this->cityRate - 60) * 7200;
}
$warPower *= getDexLog($genDexAtt, $oppDexDef);
$warPower *= $this->getCrewType()->getAttackCoef($oppose->getCrewType());
$opposeWarPowerMultiply *= $this->getCrewType()->getDefenceCoef($oppose->getCrewType());
$this->warPower = $warPower;
$this->oppose->setWarPowerMultiply($opposeWarPowerMultiply);
return [$warPower, $opposeWarPowerMultiply];
}
function addTrain(int $train){
return;
}
function addAtmos(int $atmos){
return;
}
function getComputedTrain(){
return GameConst::$maxTrainByCommand;
}
function getComputedAtmos(){
return GameConst::$maxAtmosByCommand;
}
function getComputedCriticalRatio():float{
return $this->getCrewType()->getCriticalRatio($this->getRaw());
}
function getComputedAvoidRatio():float{
return $this->getCrewType()->avoid / 100;
}
function addWin(){
}
function addLose(){
}
function finishBattle(){
throw new NotInheritedMethodException();
}
function getCharacter():int{
return 0;
}
function useBattleInitItem():bool{
return false;
}
function beginPhase():void{
$this->activatedSkill = [];
$this->computeWarPower();
}
function checkBattleBeginSkill():bool{
return false;
}
function checkBattleBeginItem():bool{
return false;
}
function applyBattleBeginSkillAndItem():bool{
return false;
}
function hasActivatedSkill(string $skillName):bool{
return $this->activatedSkill[$skillName] ?? false;
}
function activateSkill(... $skillNames){
foreach($skillNames as $skillName){
$this->activatedSkill[$skillName] = true;
}
}
function deactivateSkill(... $skillNames){
foreach($skillNames as $skillName){
$this->activatedSkill[$skillName] = false;
}
}
function checkPreActiveSkill():bool{
return false;
}
function checkActiveSkill():bool{
return false;
}
function checkPostActiveSkill():bool{
return false;
}
function applyActiveSkill(){
yield true;
}
function getHP():int{
throw new NotInheritedMethodException();
}
function decreaseHP(int $damage):int{
$this->dead += $damage;
throw new NotInheritedMethodException();
}
function increaseKilled(int $damage):int{
$this->killed += $damage;
throw new NotInheritedMethodException();
}
function calcDamage():int{
$warPower = $this->getWarPower();
$warPower *= Util::randRange(0.9, 1.1);
return Util::round($warPower);
}
function tryWound():bool{
return false;
}
function continueWar(&$noRice):bool{
//전투가 가능하면 true
$noRice = false;
return false;
}
function logBattleResult(){
$this->getLogger()->pushBattleResultTemplate($this, $this->getOppose());
}
function applyDB($db):bool{
throw new NotInheritedMethodException();
}
function criticalDamage():float{
//전특, 병종에 따라 필살 데미지가 달라질지도 모르므로 static 함수는 아닌 것으로
return Util::randRange(1.3, 2.0);
}
}
+153
View File
@@ -0,0 +1,153 @@
<?php
namespace sammo;
class WarUnitCity extends WarUnit{
protected $hp;
protected $cityRate;
function __construct($raw, $rawNation, $year, $month, $cityRate){
$this->raw = $raw;
$this->rawNation = $rawNation;
$this->isAttacker = false;
$this->cityRate = $cityRate;
$this->logger = new ActionLogger(
0,
$this->getVar('nation'),
$year,
$month,
false
);
$this->crewType = GameUnitConst::byID(GameUnitConst::T_CASTLE);
$this->hp = $this->getVar('def') * 10;
//수비자 보정
if($this->getCityVar('level') == 1){
$this->trainBonus += 5;
}
else if($this->getCityVar('level') == 3){
$this->trainBonus += 5;
}
}
function getName():string{
return $this->getVar('name');
}
function getCityVar(string $key){
return $this->raw[$key];
}
function increaseKilled(int $damage):int{
$this->killed += $damage;
$this->killedCurr += $damage;
return $this->killed;
}
function getComputedTrain(){
return $this->cityRate + $this->trainBonus;
}
function getComputedAtmos(){
return $this->cityRate + $this->atmosBonus;
}
function getHP():int{
return $this->hp;
}
function decreaseHP(int $damage):int{
$damage = min($damage, $this->hp);
$this->dead += $damage;
$this->deadCurr += $damage;
$this->hp -= $damage;
$this->increaseVarWithLimit('wall', -$damage/20, 0);
return $this->hp;
}
function continueWar(&$noRice):bool{
//전투가 가능하면 true
$noRice = false;
if($this->getHP() <= 0){
return false;
}
//도시 성벽은 쌀이 소모된다고 항복하지 않음
return true;
}
function heavyDecreseWealth(){
$this->multiplyVar('agri', 0.5);
$this->multiplyVar('comm', 0.5);
$this->multiplyVar('secu', 0.5);
}
function finishBattle(){
if($this->isFinished){
return;
}
$this->isFinished = true;
$this->updateVar('def', Util::round($this->getHP() / 10));
$this->updateVar('wall', Util::round($this->getVar('wall')));
//NOTE: 전투로 인한 사망자는 여기서 처리하지 않음
$decWealth = $this->dead / 10;
$this->increaseVarWithLimit('agri', -$decWealth, 0);
$this->increaseVarWithLimit('comm', -$decWealth, 0);
$this->increaseVarWithLimit('secu', -$decWealth, 0);
}
function addConflict():bool{
$conflict = Json::decode($this->getVar('conflict'));
$oppose = $this->getOppose();
$nationID = $oppose->getNationVar('nation');
$newConflict = false;
$dead = max(1, $this->dead);
if(!$conflict || $this->getHP() == 0){ // 선타, 막타 보너스
$dead *= 1.05;
}
if(!$conflict){
$conflict = [$nationID => $dead];
}
else if(key_exists($nationID, $conflict)){
$conflict[$nationID] += $dead;
arsort($conflict);
}
else{
$conflict[$nationID] = $dead;
arsort($conflict);
$newConflict = true;
}
$this->updateVar('conflict', Json::encode($conflict));
return $newConflict;
}
function applyDB($db):bool{
$updateVals = [];
foreach(array_keys($this->updatedVar) as $key){
$updateVals[$key] = $this->raw[$key];
}
if(!$updateVals){
return false;
}
$db->update('city', $updateVals, 'city=%i', $this->raw['city']);
$this->getLogger()->rollback(); //수비 도시의 로그는 기록하지 않음
return $db->affectedRows() > 0;
}
}
+968
View File
@@ -0,0 +1,968 @@
<?php
namespace sammo;
class WarUnitGeneral extends WarUnit{
protected $rawCity;
protected $bonusPhase = 0;
function __construct($raw, $rawCity, $rawNation, $isAttacker, $year, $month){
setLeadershipBonus($raw, $rawNation['level']);
$this->raw = $raw;
$this->rawCity = $rawCity; //read-only
$this->rawNation = $rawNation; //read-only
$this->isAttacker = $isAttacker;
$this->logger = new ActionLogger(
$this->getVar('no'),
$this->getVar('nation'),
$year,
$month,
false
);
$this->crewType = GameUnitConst::byID($this->getVar('crewtype'));
$cityLevel = $this->getCityVar('level');
if($isAttacker){
//공격자 보정
if($cityLevel == 2){
$this->atmosBonus += 5;
}
if($rawNation['capital'] == $this->getCityVar('city')){
$this->atmosBonus += 5;
}
}
else{
//수비자 보정
if($cityLevel == 1){
$this->trainBonus += 5;
}
else if($cityLevel == 3){
$this->trainBonus += 5;
}
}
}
function getName():string{
return $this->getVar('name');
}
function getCityVar(string $key){
return $this->rawCity[$key];
}
function getSpecialDomestic():int{
return $this->getVar('special');
}
function setOppose(?WarUnit $oppose){
parent::setOppose($oppose);
$this->increaseVar('warnum', 1);
if($this->isAttacker){
$this->updateVar('recwar', $this->getVar('turntime'));
}
else if($oppose !== null){
$this->updateVar('recwar', $oppose->getVar('turntime'));
}
}
function getSpecialWar():int{
return $this->getVar('special2');
}
function getCharacter():int{
return $this->getVar('personal');
}
function getItem():int{
return $this->getVar('item');
}
function getMaxPhase():int{
$phase = $this->getCrewType()->speed;
if($this->getSpecialWar() == 60){
$phase += 1;
}
return $phase + $this->bonusPhase;
}
function addTrain(int $train){
$this->increaseVarWithLimit('train', $train, 0, GameConst::$maxTrainByWar);
}
function addAtmos(int $atmos){
$this->increaseVarWithLimit('atmos', $train, 0, GameConst::$maxAtmosByWar);
}
function getComputedTrain(){
$train = $this->getVar('train');
$train += $this->trainBonus;
return $train;
}
function getComputedAtmos(){
$atmos = $this->getVar('atmos');
$atmos += $this->atmosBonus;
return $atmos;
}
function getComputedCriticalRatio():float{
$critialRatio = $this->getCrewType()->getCriticalRatio($this->getRaw());
$specialWar = $this->getSpecialWar();
$item = $this->getItem();
if($specialWar == 61){
if($this->isAttacker){
$critialRatio += 0.1;
}
}
else if($specialWar == 71){
$critialRatio += 0.2;
}
return $critialRatio;
}
function getComputedAvoidRatio():float{
$specialWar = $this->getSpecialWar();
$item = $this->getItem();
$avoidRatio = $this->getCrewType()->avoid / 100;
$avoidRatio *= $this->getComputedTrain() / 100;
//특기보정 : 궁병
if($specialWar == 51){
$avoidRatio += 0.2;
}
//도구 보정 : 둔갑천서, 태평요술
if($item == 26 || $item == 25){
$avoidRatio += 0.2;
}
return $avoidRatio;
}
function addWin(){
$this->increaseVar('killnum', 1);
$this->multiplyVarWithLimit('atmos', 1.1, null, GameConst::$maxAtmosByWar);
$this->addStatExp(1);
}
function addStatExp(int $value = 1){
if($this->crewType->armType == GameUnitConst::T_WIZARD) { // 귀병
$this->increaseVar('intel2', $value);
} elseif($this->crewType->armType == GameUnitConst::T_SIEGE) { // 차병
$this->increaseVar('leader2', $value);
} else {
$this->increaseVar('power2', $value);
}
}
function addLevelExp(float $value){
if(!$this->isAttacker){
$value *= 0.8;
}
$value *= getCharExpMultiplier($this->getCharacter());
$this->increaseVar('experience', $value);
}
function addDedication(float $value){
$value *= getCharDedMultiplier($this->getCharacter());
$this->increaseVar('dedication', $value);
}
function addLose(){
$this->increaseVar('deathnum', 1);
$this->addStatExp(1);
}
protected function getWarPowerMultiplyBySpecialWar():array{
//TODO: 장기적으로 if문이 아니라 객체를 이용하여 처리해야함
$myWarPowerMultiply = 1.0;
$opposeWarPowerMultiply = 1.0;
$specialWar = $this->getSpecialWar();
if($specialWar == 53){
if($this->getOppose() instanceof WarUnitCity){
$myWarPowerMultiply *= 2;
}
}
else if($specialWar == 52){
if($this->isAttacker){
$myWarPowerMultiply *= 1.20;
}
else{
$myWarPowerMultiply *= 1.10;
}
}
else if($specialWar == 60){
if($this->isAttacker){
$myWarPowerMultiply *= 1.10;
}
}
else if($specialWar == 61){
$myWarPowerMultiply *= 1.10;
}
else if($specialWar == 50){
if($this->isAttacker){
$opposeWarPowerMultiply *= 0.9;
}
else{
$opposeWarPowerMultiply *= 0.8;
}
}
else if($specialWar == 62){
if ($this->isAttacker) {
$opposeWarPowerMultiply *= 0.9;
}
else{
$myWarPowerMultiply *= 1.1;
}
}
else if($specialWar == 75){
$opposeCrewType = $this->oppose->getCrewType();
if($opposeCrewType->reqCities || $opposeCrewType->reqRegions){
$myWarPowerMultiply *= 1.1;
$opposeWarPowerMultiply *= 0.9;
}
}
return [$myWarPowerMultiply, $opposeWarPowerMultiply];
}
function computeWarPower(){
[$warPower,$opposeWarPowerMultiply] = parent::computeWarPower();
$generalNo = $this->getVar('no');
$genLevel = $this->getVar('level');
if($this->isAttacker){
if($genLevel == 12){
$warPower *= 1.10;
}
else if($genLevel == 11 | $genLevel == 10 || $genLevel == 8 || $genLevel == 6){
$warPower *= 1.05;
}
}
else{
if($genLevel == 12){
$opposeWarPowerMultiply *= 0.90;
}
else if($genLevel == 11 || $genLevel == 9 || $genLevel == 7 || $genLevel == 5){
$opposeWarPowerMultiply *= 0.95;
}
else if($genLevel == 4 && $generalNo == $this->getCityVar('gen1')){
$opposeWarPowerMultiply *= 0.95;
}
else if($genLevel == 3 && $generalNo == $this->getCityVar('gen2')){
$opposeWarPowerMultiply *= 0.95;
}
else if($genLevel == 2 && $generalNo == $this->getCityVar('gen3')){
$opposeWarPowerMultiply *= 0.95;
}
}
$expLevel = $this->getVar('explevel');
if($this->getOppose() instanceof WarUnitCity){
$warPower *= 1 + $expLevel / 600;
}
else{
$warPower /= max(0.01, 1 - $expLevel / 300);
$opposeWarPowerMultiply *= max(0.01, 1 - $expLevel / 300);
}
[$specialMyWarPowerMultiply, $specialOpposeWarPowerMultiply] = $this->getWarPowerMultiplyBySpecialWar();
$warPower *= $specialMyWarPowerMultiply;
$opposeWarPowerMultiply *= $specialOpposeWarPowerMultiply;
$this->warPower = $warPower;
$this->oppose->setWarPowerMultiply($opposeWarPowerMultiply);
return [$warPower,$opposeWarPowerMultiply];
}
///전투 개시 시에 작동하여 1회에만 작동하는 아이템
function useBattleInitItem():bool{
$item = $this->getItem();
if($item == 0){
return false;
}
$itemActivated = false;
$itemConsumed = false;
$itemName = getItemName($item);
if($item == 3){
//탁주 사용
$this->addAtmos(3);
$itemActivated = true;
$itemConsumed = true;
}
else if($item >= 14 && $item <= 16){
//의적주, 두강주, 보령압주 사용
$this->addAtmos(5);
$itemActivated = true;
}
else if($item >= 19 && $item <= 20){
//춘화첩, 초선화 사용
$this->addAtmos(7);
$itemActivated = true;
}
else if($item == 4){
//청주 사용
$this->addTrain(3);
$itemActivated = true;
$itemConsumed = true;
}
else if($item >= 12 && $item <= 13){
//과실주, 이강주 사용
$this->addTrain(5);
$itemActivated = true;
}
else if($item >= 18 && $item <= 18){
//철벽서, 단결도 사용
$this->addTrain(7);
$itemActivated = true;
}
if($itemConsumed){
$this->updateVar('item', 0);
$josaUl = JosaUtil::pick($itemName, '을');
$this->getLogger()->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 사용!", ActionLogger::PLAIN);
}
return $itemActivated;
}
///전투 개시 시에 작동하여 매 장수마다 작동하는 스킬
function checkBattleBeginSkill():bool{
$skillResult = false;
$oppose = $this->getOppose();
$specialWar = $this->getSpecialWar();
if (
$specialWar == 70 &&
$this->oppose instanceof WarUnitGeneral &&
!$this->hasActivatedSkill('저격') &&
Util::randBool(1/3)
) {
$this->activateSkill('저격');
$skillResult = true;
}
return $skillResult;
}
///전투 개시 시에 작동하여 매 장수마다 작동하는 아이템
function checkBattleBeginItem():bool{
$item = $this->getItem();
$oppose = $this->getOppose();
if(!$item){
return false;
}
$itemActivated = false;
$itemConsumed = false;
$itemName = getItemName($item);
if(
$item == 2 &&
$this->oppose instanceof WarUnitGeneral &&
!$this->hasActivatedSkill('저격') &&
Util::randBool(1/5)
){
$itemActivated = true;
$itemConsumed = true;
$this->activateSkill('저격');
}
if($itemConsumed){
//NOTE: 소비 아이템은 하나인가?, 1회용인가?
$this->updateVar('item', 0);
$josaUl = JosaUtil::pick($itemName, '을');
$this->getLogger()->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 사용!", ActionLogger::PLAIN);
}
return $itemActivated;
}
function applyBattleBeginSkillAndItem():bool{
$result = false;
$oppose = $this->getOppose();
if($oppose->hasActivatedSkill('저격')){
$result = true;
$oppose->getLogger()->pushGeneralActionLog("상대를 <C>저격</>했다!", ActionLogger::PLAIN);
$oppose->getLogger()->pushGeneralBattleDetailLog("상대를 <C>저격</>했다!", ActionLogger::PLAIN);
$this->getLogger()->pushGeneralActionLog("상대에게 <R>저격</>당했다!", ActionLogger::PLAIN);
$this->getLogger()->pushGeneralBattleDetailLog("상대에게 <R>저격</>당했다!", ActionLogger::PLAIN);
$this->increaseVarWithLimit('injury', Util::randRangeInt(20, 60), null, 80);
}
return $result;
}
function getHP():int{
return $this->getVar('crew');
}
function addDex(GameUnitDetail $crewType, float $exp){
$armType = $crewType->armType;
if($armType == GameUnitConst::T_CASTLE){
$armType = GameUnitConst::T_SIEGE;
}
if($armType < 0){
return;
}
if($armType == GameUnitConst::T_WIZARD) {
$exp *= 0.9;
}
else if($armType == GameUnitConst::T_SIEGE) {
$exp *= 0.9;
}
$exp *= ($this->getComputedTrain() + $this->getComputedAtmos()) / 200;
$ntype = $armType*10;
$dexType = "dex{$ntype}";
$this->increaseVar($dexType, $exp);
}
function decreaseHP(int $damage):int{
$damage = min($damage, $this->getVar('crew'));
$this->dead += $damage;
$this->deadCurr += $damage;
$this->increaseVar('crew', -$damage);
$addDex = $damage;
if(!$this->isAttacker){
$addDex *= 0.9;
}
$this->addDex($this->oppose->getCrewType(), $addDex);
return $this->getVar('crew');
}
function increaseKilled(int $damage):int{
$this->addLevelExp($damage / 50);
$rice = $damage / 100;
if(!$this->isAttacker){
$rice *= 0.8;
}
$rice *= getCharExpMultiplier($this->getCharacter());
$rice *= $this->crewType->rice;
$rice *= getTechCost($this->getNationVar('tech'));
$this->increaseVarWithLimit('rice', -$rice, 0);
$addDex = $damage;
if(!$this->isAttacker){
$addDex *= 0.9;
}
$this->addDex($this->getCrewType(), $addDex);
$this->killed += $damage;
$this->killedCurr += $damage;
return $this->killed;
}
function checkPreActiveSkill():bool{
$activated = false;
$oppose = $this->getOppose();
$specialWar = $this->getSpecialWar();
$item = $this->getItem();
$crewType = $this->getCrewType();
if(
!$this->hasActivatedSkill('특수') &&
!$this->isAttacker &&
$crewType->name == '목우'
){
//XXX: 병종에 특수 스킬이 달려있도록 설정해야함
$ratio = $this->getComputedAtmos() + $this->getComputedTrain();
if(Util::randBool($ratio / 400)){
$this->activateSkill('특수', '저지');
$activated = true;
}
}
if(
$specialWar == 63 &&
$this->getPhase() == 0 &&
$this->getHP() >= 1000 &&
$this->getComputedAtmos() >= 90 &&
$this->getComputedTrain() >= 90
){
$this->activateSkill('위압');
$activated = true;
}
return $activated;
}
function checkActiveSkill():bool{
$activated = false;
$oppose = $this->getOppose();
$specialWar = $this->getSpecialWar();
$item = $this->getItem();
$crewType = $this->getCrewType();
if ($specialWar == 60 && $oppose->hasActivatedSkill('저지')) {
$oppose->deactivateSkill('특수', '저지');
$activated = true;
}
if(
!$this->hasActivatedSkill('특수') &&
Util::randBool($this->getComputedCriticalRatio())
){
$this->activateSkill('특수', '필살시도', '필살');
$activated = true;
}
if(
!$this->hasActivatedSkill('특수') &&
Util::randBool($this->getComputedAvoidRatio())
){
$this->activateSkill('특수', '회피시도', '회피');
$activated = true;
}
//계략
if($crewType->magicCoef){
$magicRatio = getGeneralIntel($this->raw, true, true, true, false) / 100;
$magicRatio *= $crewType->magicCoef;
if($specialWar == 41){
$magicRatio += 0.2;
}
if(Util::randBool($magicRatio)){
$magicSuccessRatio = 0.7;
if($specialWar == 40){
$magicSuccessRatio += 0.2;
}
if($specialWar == 41){
$magicSuccessRatio += 0.2;
}
if($specialWar == 42){
$magicSuccessRatio += 0.1;
}
if($specialWar == 44){
$magicSuccessRatio += 1;
}
if($oppose instanceof WarUnitCity){
$magic = Util::choiceRandom(['급습', '위보',' 혼란']);
}
else{
$magic = Util::choiceRandom(['위보', '매복', '반목', '화계', '혼란']);
}
$this->activateSkill('계략시도', $magic);
if(Util::randBool($magicSuccessRatio)){
$this->activateSkill('계략');
}
else{
$this->activateSkill('계략실패');
}
}
}
//의술
if($specialWar == 73 && Util::randBool(0.2)){
$this->activateSkill('치료');
$activated = true;
}
return $activated;
}
function checkPostActiveSkill():bool{
$activated = false;
$oppose = $this->getOppose();
$specialWar = $this->getSpecialWar();
$item = $this->getItem();
$crewType = $this->getCrewType();
if($specialWar == 74 && $oppose->hasActivatedSkill('필살')){
if($this->isAttacker){
if(Util::randBool(1/3)){
$this->activateSkill('진노', '격노');
$activated = true;
}
else if(Util::randBool(1/4)){
$this->activateSkill('격노');
$activated = true;
}
}
else{
if(Util::randBool(1/2)){
$this->activateSkill('격노');
$activated = true;
}
}
}
if(
$specialWar == 74 &&
$oppose->hasActivatedSkill('회피')
){
if($this->isAttacker){
if(Util::randBool(1/3)){
$this->activateSkill('진노', '격노');
$oppose->deactivateSkill('회피');
$activated = true;
}
else if(Util::randBool(1/4)){
$this->activateSkill('격노');
$oppose->deactivateSkill('회피');
$activated = true;
}
}
else{
if(Util::randBool(1/2)){
$this->activateSkill('격노');
$oppose->deactivateSkill('회피');
$activated = true;
}
}
}
if(
($item == 23 || $item == 24) &&
!$this->hasActivatedSkill('치료') &&
Util::randBool(0.2)
){
$this->activateSkill('치료');
$activated = true;
}
//계략
if(
$specialWar == 45 &&
$oppose->hasActivatedSkill('계략') &&
Util::randBool(0.3)
){
$this->activateSkill('반계');
$oppose->deactivateSkill('계략');
$activated = true;
}
if(
$specialWar == 42 &&
$this->hasActivatedSkill('계략')
){
$this->warPowerMultiply *= 1.3;
}
if(
$specialWar == 43 &&
$this->hasActivatedSkill('계략')
){
$this->warPowerMultiply *= 1.5;
}
return $activated;
}
function applyActiveSkill(){
$oppose = $this->getOppose();
$crewType = $this->getCrewType();
$specialWar = $this->getSpecialWar();
$thisLogger = $this->getLogger();
$opposeLogger = $oppose->getLogger();
if($this->hasActivatedSkill('저지')){
$this->setWarPowerMultiply(0);
$oppose->setWarPowerMultiply(0);
$thisLogger->pushGeneralBattleDetailLog('상대를 <C>저지</>했다!</>');
$opposeLogger->pushGeneralBattleDetailLog('저지</>당했다!</>');
//저지는 특수함.
return;
}
yield true;
//계략 세트
if($this->hasActivatedSkill('계략')){
$tableToGeneral = [
'위보'=>1.2,
'매복'=>1.4,
'반목'=>1.6,
'화계'=>1.8,
'혼란'=>2.0
];
$tableToCity = [
'급습'=>1.2,
'위보'=>1.4,
'혼란'=>1.6
];
if($specialWar == 45){
$tableToGeneral['반목'] *= 2;
}
if($oppose instanceof WarUnitCity){
$table = $tableToCity;
}
else{
$table = $tableToGeneral;
}
foreach($table as $skillKey => $skillMultiply){
if($this->hasActivatedSkill($skillKey)){
$josaUl = \sammo\JosaUtil::pick($skillKey, '을');
$thisLogger->pushGeneralBattleDetailLog("<D>{$skillKey}</>{$josaUl} <C>성공</>했다!");
$opposeLogger->pushGeneralBattleDetailLog("<D>{$skillKey}</>에 당했다!");
$this->multiplyWarPowerMultiply($skillMultiply);
break;
}
}
}
yield true;
//반계 세트
if($this->hasActivatedSkill('반계')){
$table = [
'위보'=>1.2,
'매복'=>1.4,
'반목'=>1.6,
'화계'=>1.8,
'혼란'=>2.0
];
foreach($table as $skillKey => $skillMultiply){
if($oppose->hasActivatedSkill($skillKey)){
$josaUl = \sammo\JosaUtil::pick($skillKey, '을');
$thisLogger->pushGeneralBattleDetailLog("<C>●</><C>반계</>로 상대의 <D>{$skillKey}</>{$josaUl} 되돌렸다!");
$opposeLogger->pushGeneralBattleDetailLog("<D>{$skillKey}</>{$josaUl} <R>역으로</> 당했다!");
$this->multiplyWarPowerMultiply($skillMultiply);
break;
}
}
}
yield true;
//계략 실패 세트
if($this->hasActivatedSkill('계략실패')){
$tableToGeneral = [
'위보'=>1.1,
'매복'=>1.2,
'반목'=>1.3,
'화계'=>1.4,
'혼란'=>1.5
];
$tableToCity = [
'급습'=>1.1,
'위보'=>1.2,
'혼란'=>1.3
];
if($oppose instanceof WarUnitCity){
$table = $tableToCity;
}
else{
$table = $tableToGeneral;
}
foreach($table as $skillKey => $skillMultiply){
if($this->hasActivatedSkill($skillKey)){
$josaUl = \sammo\JosaUtil::pick($skillKey, '을');
$thisLogger->pushGeneralBattleDetailLog("<D>{$skillKey}</>{$josaUl} <C>실패</>했다!");
$opposeLogger->pushGeneralBattleDetailLog("<D>{$skillKey}</>{$josaUl} 간파했다!");
$this->multiplyWarPowerMultiply($skillMultiply);
$oppose->multiplyWarPowerMultiply(1/$skillMultiply);
break;
}
}
}
yield true;
if($this->hasActivatedSkill('치료')){
$thisLogger->pushGeneralBattleDetailLog("<C>치료</>했다!</>");
$oppose->multiplyWarPowerMultiply(1/1.5);
}
yield true;
if($this->hasActivatedSkill('필살')){
$thisLogger->pushGeneralBattleDetailLog('<C>필살</>공격!</>');
$opposeLogger->pushGeneralBattleDetailLog('상대의 <R>필살</>공격!</>');
$this->multiplyWarPowerMultiply($this->criticalDamage());
}
yield true;
if($this->hasActivatedSkill('회피')){
$thisLogger->pushGeneralBattleDetailLog('회피</>했다!</>');
$opposeLogger->pushGeneralBattleDetailLog('상대가 <R>회피</>했다!</>"');
$oppose->multiplyWarPowerMultiply(0.2);
}
yield true;
if($this->hasActivatedSkill('진노')){
if($oppose->hasActivatedSkill('필살')){
$thisLogger->pushGeneralBattleDetailLog('상대의 필살 공격에 <C>진노</>했다!</>');
$opposeLogger->pushGeneralBattleDetailLog('필살 공격에 상대가 <R>진노</>했다!</>');
}
else if($oppose->hasActivatedSkill('회피시도')){
$thisLogger->pushGeneralBattleDetailLog('상대의 회피 시도에 <C>진노</>했다!</>');
$opposeLogger->pushGeneralBattleDetailLog('회피 시도에 상대가 <R>진노</>했다!</>');
}
$this->bonusPhase += 1;
$this->multiplyWarPowerMultiply($this->criticalDamage());
}
else if($this->hasActivatedSkill('격노')){
if($oppose->hasActivatedSkill('필살')){
$thisLogger->pushGeneralBattleDetailLog('상대의 필살 공격에 <C>격노</>했다!</>');
$opposeLogger->pushGeneralBattleDetailLog('필살 공격에 상대가 <R>격노</>했다!</>');
}
else if($oppose->hasActivatedSkill('회피시도')){
$thisLogger->pushGeneralBattleDetailLog('상대의 회피 시도에 <C>격노</>했다!</>');
$opposeLogger->pushGeneralBattleDetailLog('회피 시도에 상대가 <R>격노</>했다!</>');
}
$this->multiplyWarPowerMultiply($this->criticalDamage());
}
yield true;
if($this->hasActivatedSkill('위압')){
$thisLogger->pushGeneralBattleDetailLog('상대에게 <C>위압</>을 줬다!</>');
$opposeLogger->pushGeneralBattleDetailLog('상대에게 <R>위압</>받았다!</>');
$oppose->setWarPowerMultiply(0);
}
yield true;
}
function tryWound():bool{
if(!Util::randBool(0.05)){
return false;
}
$this->increaseVarWithLimit('injury', Util::randRangeInt(10, 80), null, 80);
$this->getLogger()->pushGeneralActionLog("전투중 <R>부상</>당했다!", ActionLogger::PLAIN);
return true;
}
function continueWar(&$noRice):bool{
if($this->getHP() <= 0){
$noRice = false;
return false;
}
if($this->getVar('rice') <= $this->getHP() / 100){
$noRice = true;
return false;
}
return true;
}
///checkAbility의 method 버전
function checkStatChange():bool{
//FIXME: 장기적으로는 General 클래스가 별도로 있어야 함
$logger = $this->getLogger();
$limit = GameConst::$upgradeLimit;
$table = [
['통솔', 'leader'],
['무력', 'power'],
['지력', 'intel'],
];
$result = false;
foreach($table as [$statNickName, $statName]){
$statExpName = $statName.'2';
if($this->getVar($statExpName) < 0){
$logger->pushGeneralActionLog("<R>{$statNickName}</>이 <C>1</> 떨어졌습니다!", ActionLogger::PLAIN);
$this->increaseVar($statExpName, $limit);
$this->increaseVar($statName, -1);
$result = true;
}
else if($this->getVar($statExpName) >= $limit){
$logger->pushGeneralActionLog("<R>{$statNickName}</>이 <C>1</> 올랐습니다!", ActionLogger::PLAIN);
$this->increaseVar($statExpName, -$limit);
$this->increaseVar($statName, 1);
$result = true;
}
}
return $result;
}
function finishBattle(){
if($this->isFinished){
return;
}
$this->isFinished = true;
$this->increaseVar('killcrew', $this->killed);
$this->increaseVar('deathcrew', $this->dead);
$this->updateVar('rice', Util::round($this->getVar('rice')));
$this->updateVar('experience', Util::round($this->getVar('experience')));
$this->updateVar('dedication', Util::round($this->getVar('dedication')));
$this->checkStatChange();
}
/**
* @param \MeekroDB $db
*/
function applyDB($db):bool{
$updateVals = [];
foreach(array_keys($this->updatedVar) as $key){
$updateVals[$key] = $this->raw[$key];
}
if(!$updateVals){
return false;
}
$db->update('general', $updateVals, 'no=%i', $this->raw['no']);
$this->getLogger()->flush();
return $db->affectedRows() > 0;
}
}
+7
View File
@@ -0,0 +1,7 @@
<?php
namespace sammo;
class CityConst extends CityConstBase{
}
+125
View File
@@ -0,0 +1,125 @@
<?php
namespace sammo;
class CityConst extends CityConstBase{
public static $regionMap = [
'호넷 마인령'=>1,1=>'호넷 마인령',
'케이브리스 마인령'=>2,2=>'케이브리스 마인령',
'카라의 숲'=>3,3=>'카라의 숲',
'샹그릴라'=>4,4=>'샹그릴라',
'제스 북부'=>5,5=>'제스 북부',
'제스 남부'=>6,6=>'제스 남부',
'헬만 서부'=>7,7=>'헬만 서부',
'헬만 동부'=>8,8=>'헬만 동부',
'리자스 남부'=>9,9=>'리자스 남부',
'리자스 북부'=>10,10=>'리자스 북부',
'JAPAN'=>11,11=>'JAPAN',
'자유도시 동부'=>12,12=>'자유도시 동부',
'자유도시 서부'=>13,13=>'자유도시 서부',
'AL교'=>14,14=>'AL교',
];
protected static $initCity = [
//id, 도시, 규모, 인구, 농, 상, 치, 성, 수,(x100)지역, x, y, 연결도시
[ 1, '구 마왕성', '특', 8000,120,120,100,120,120, '호넷 마인령', 35, 142, ['악의 탑','한탄의 협곡','유황의 숲']],
[ 2, '악의 탑', '이', 3500, 40, 40, 20, 40, 40, '호넷 마인령', 45, 40, ['반리요새 A','구 마왕성']],
[ 3, '실키의 성', '중', 5500, 80, 80, 60, 80, 80, '호넷 마인령', 45, 270, ['유황의 숲','카스케도바우','죽음의 대지']],
[ 4, '카스케도바우', '중', 5500, 80, 80, 60, 80, 80, '호넷 마인령', 120, 276, ['실키의 성','케셀링크의 성']],
[ 5, '붉은 집', '수', 2500, 20, 20, 20, 40, 40, '케이브리스 마인령', 70, 335, ['케이브리스의 성','케셀링크의 성']],
[ 6, '케셀링크의 성', '대', 7000,100,100, 80,100,100, '케이브리스 마인령', 135, 338, ['붉은 집','메이드의 묘지','카스케도바우','뼈의 숲']],
[ 7, '케이브리스의 성', '특', 8000,120,120,100,120,120, '케이브리스 마인령', 37, 384, ['붉은 집','푸른 집','죽음의 대지']],
[ 8, '푸른 집', '수', 2500, 20, 20, 20, 40, 40, '케이브리스 마인령', 59, 446, ['케이브리스의 성','메이드의 묘지','카미라의 성']],
[ 9, '한탄의 협곡', '소', 4500, 60, 60, 40, 60, 60, '호넷 마인령', 97, 152, ['구 마왕성','반리요새 B']],
[10, '뼈의 숲', '소', 4500, 60, 60, 40, 60, 60, '케이브리스 마인령', 160, 386, ['케셀링크의 성','마지노 A']],
[11, '유황의 숲', '소', 4500, 60, 60, 40, 60, 60, '호넷 마인령', 72, 209, ['구 마왕성','실키의 성']],
[12, '카미라의 성', '대', 7000,100,100, 80,100,100, '케이브리스 마인령', 130, 460, ['푸른 집','갈라놓은 숲']],
[13, '메이드의 묘지', '이', 3500, 40, 40, 20, 40, 40, '케이브리스 마인령', 102, 380, ['케셀링크의 성','푸른 집']],
[14, '갈라놓은 숲', '소', 4500, 60, 60, 40, 60, 60, '케이브리스 마인령', 186, 472, ['카미라의 성','마지노 B']],
[15, '죽음의 대지', '이', 3500, 40, 40, 20, 40, 40, '케이브리스 마인령', 10, 320, ['케이브리스의 성','실키의 성']],
[16, '녹의 마을', '소', 4500, 60, 60, 40, 60, 60, '카라의 숲', 202, 290, ['마지노 A','파리티라온']],
[17, '펜실 카우', '이', 3500, 40, 40, 20, 40, 40, '카라의 숲', 297, 267, ['파리티라온','라보리']],
[18, '샹그릴라', '대', 7000,100,100, 80,100,100, '샹그릴라', 374, 272, ['스도리 13','보르고 Z','사바사바','릿치']],
[19, '파리티라온', '중', 5500, 80, 80, 60, 80, 80, '제스 북부', 259, 332, ['녹의 마을','마지노 A','왕자의 탑','펜실 카우']],
[20, '왕자의 탑', '소', 4500, 60, 60, 40, 60, 60, '제스 북부', 259, 367, ['파리티라온','도약의 탑','일요일의 탑','라그나로크 아크']],
[21, '도약의 탑', '소', 4500, 60, 60, 40, 60, 60, '제스 남부', 265, 406, ['왕자의 탑','라그나로크 아크','탄창의 탑','마크']],
[22, '일요일의 탑', '소', 4500, 60, 60, 40, 60, 60, '제스 북부', 324, 358, ['왕자의 탑','라그나로크 아크','탄창의 탑','나가르모르']],
[23, '탄창의 탑', '소', 4500, 60, 60, 40, 60, 60, '제스 남부', 331, 409, ['도약의 탑','라그나로크 아크','일요일의 탑','올드제스']],
[24, '라그나로크 아크', '특', 8000,120,120,100,120,120, '제스 북부', 295, 385, ['왕자의 탑','도약의 탑','도약의 탑','탄창의 탑','일요일의 탑']],
[25, '알텐누', '중', 5500, 80, 80, 60, 80, 80, '제스 남부', 293, 482, ['마크','마지노 B']],
[26, '마크', '중', 5500, 80, 80, 60, 80, 80, '제스 남부', 288, 436, ['알텐누','호박성','도약의 탑']],
[27, '호박성', '이', 3500, 40, 40, 20, 40, 40, '제스 남부', 328, 458, ['마크','올드제스']],
[28, '올드제스', '특', 8000,120,120,100,120,120, '제스 남부', 367, 444, ['탄창의 탑','호박성','테이브','카이즈']],
[29, '테이브', '소', 4500, 60, 60, 40, 60, 60, '제스 남부', 385, 406, ['이탈리아','올드제스']],
[30, '이탈리아', '대', 7000,100,100, 80,100,100, '제스 북부', 375, 361, ['테이브','사바사바','아담의탑']],
[31, '나가르모르', '중', 5500, 80, 80, 60, 80, 80, '제스 북부', 322, 322, ['일요일의 탑','사바사바']],
[32, '사바사바', '대', 7000,100,100, 80,100,100, '제스 북부', 375, 324, ['나가르모르','이탈리아','샹그릴라']],
[33, '아담의탑', '진', 2500, 20, 20, 20, 40, 40, '제스 북부', 420, 340, ['이탈리아','파라파라성채']],
[34, '마지노 A', '관', 2500, 20, 20, 20, 90, 90, '제스 북부', 215, 365, ['뼈의 숲','녹의 마을','파리티라온']],
[35, '마지노 B', '관', 2500, 20, 20, 20, 90, 90, '제스 남부', 243, 477, ['갈라놓은 숲','알텐누']],
[36, '이코마', '중', 5500, 80, 80, 60, 80, 80, '헬만 서부', 211, 60, ['반리요새 A','거대전함','워크랜드','로렌그라드']],
[37, '워크랜드', '소', 4500, 60, 60, 40, 60, 60, '헬만 서부', 177, 90, ['이코마','로렌그라드']],
[38, '로렌그라드', '대', 7000,100,100, 80,100,100, '헬만 서부', 200, 126, ['파르나스','랑그바우','이코마','반리요새 B','워크랜드']],
[39, '파르나스', '중', 5500, 80, 80, 60, 80, 80, '헬만 서부', 204, 171, ['로렌그라드','세미타포']],
[40, '라보리', '중', 5500, 80, 80, 60, 80, 80, '헬만 서부', 225, 219, ['펜실 카우','스도리 17']],
[41, '랑그바우', '특', 8000,120,120,100,120,120, '헬만 서부', 263, 135, ['로렌그라드','마이크로그라드']],
[42, '거대전함', '이', 3500, 40, 40, 20, 40, 40, '헬만 서부', 273, 21, ['이코마','파스','호라가의 탑','시베리아']],
[43, '세미타포', '소', 4500, 60, 60, 40, 60, 60, '헬만 서부', 268, 174, ['파르나스','스도리 17']],
[44, '스도리 17', '진', 2500, 20, 20, 20, 40, 40, '헬만 서부', 296, 214, ['라보리','세미타포','스도리 13']],
[45, '스도리 13', '진', 2500, 20, 20, 20, 40, 40, '헬만 서부', 359, 217, ['샹그릴라','폰','스도리 17','코사크','보르고 Z']],
[46, '마이크로그라드', '소', 4500, 60, 60, 40, 60, 60, '헬만 서부', 316, 166, ['폰','랑그바우','스도리 10']],
[47, '폰', '중', 5500, 80, 80, 60, 80, 80, '헬만 서부', 377, 187, ['마이크로그라드','스도리 13','코사크']],
[48, '파스', '중', 5500, 80, 80, 60, 80, 80, '헬만 서부', 286, 90, ['거대전함','큐로브','스도리 10']],
[49, '큐로브', '소', 4500, 60, 60, 40, 60, 60, '헬만 서부', 341, 96, ['파스','소로토이']],
[50, '스도리 10', '진', 2500, 20, 20, 20, 40, 40, '헬만 서부', 337, 137, ['파스','로제스그라드','마이크로그라드']],
[51, '소로토이', '소', 4500, 60, 60, 40, 60, 60, '헬만 동부', 382, 119, ['큐로브','바바로프스']],
[52, '로제스그라드', '특', 8000,120,120,100,120,120, '헬만 동부', 401, 148, ['스도리 10','바바로프스','아크그라드']],
[53, '코사크', '중', 5500, 80, 80, 60, 80, 80, '헬만 동부', 419, 204, ['스도리 13','보르고 Z','폰']],
[54, '아크그라드', '소', 4500, 60, 60, 40, 60, 60, '헬만 동부', 452, 179, ['로그 B','로제스그라드','야크트크']],
[55, '야크트크', '소', 4500, 60, 60, 40, 60, 60, '헬만 동부', 437, 129, ['아크그라드','바바로프스','고라크']],
[56, '시베리아', '대', 7000,100,100, 80,100,100, '헬만 동부', 394, 55, ['바바로프스','호라가의 탑','거대전함']],
[57, '바바로프스', '중', 5500, 80, 80, 60, 80, 80, '헬만 동부', 418, 89, ['시베리아','야크트크','소로토이','로제스그라드']],
[58, '호라가의 탑', '관', 2500, 20, 20, 20, 90, 90, '헬만 동부', 561, 20, ['시베리아','거대전함','떨어진 궁도']],
[59, '고라크', '중', 5500, 80, 80, 60, 80, 80, '헬만 동부', 478, 146, ['블라디보스토크','로그 A','야크트크']],
[60, '블라디보스토크', '이', 3500, 40, 40, 20, 40, 40, '헬만 동부', 500, 109, ['고라크','로그 A']],
[61, '보르고 Z', '관', 2500, 20, 20, 20, 90, 90, '헬만 동부', 436, 245, ['코사크','스도리 13','로그 B', '샹그릴라']],
[62, '로그 A', '관', 2500, 20, 20, 20, 90, 90, '헬만 동부', 506, 183, ['고라크','블라디보스토크','로그 B','스케일']],
[63, '로그 B', '관', 2500, 20, 20, 20, 90, 90, '헬만 동부', 475, 216, ['아크그라드','로그 A','보르고 Z','마우네스']],
[64, '반리요새 A', '진', 2500, 20, 20, 20, 40, 40, '헬만 서부', 149, 18, ['악의 탑','이코마']],
[65, '반리요새 B', '진', 2500, 20, 20, 20, 40, 40, '헬만 서부', 151, 153, ['로렌그라드','한탄의 협곡']],
[66, '파라파라성채', '진', 2500, 20, 20, 20, 40, 40, '리자스 남부', 449, 315, ['아담의탑','릿치']],
[67, '릿치', '중', 5500, 80, 80, 60, 80, 80, '리자스 남부', 476, 288, ['푸아','마우네스','파라파라성채','샹그릴라']],
[68, '푸아', '소', 4500, 60, 60, 40, 60, 60, '리자스 남부', 528, 289, ['릿치','록아스']],
[69, '마우네스', '소', 4500, 60, 60, 40, 60, 60, '리자스 남부', 502, 250, ['릿치','로그 B','노스']],
[70, '스케일', '대', 7000,100,100, 80,100,100, '리자스 북부', 542, 198, ['로그 A','아란','노스']],
[71, '아란', '중', 5500, 80, 80, 60, 80, 80, '리자스 북부', 596, 154, ['떨어진 궁도','포나라','스케일','브리테리아']],
[72, '떨어진 궁도', '이', 3500, 40, 40, 20, 40, 40, '리자스 북부', 598, 111, ['호라가의 탑','아란']],
[73, '포나라', '소', 4500, 60, 60, 40, 60, 60, '리자스 북부', 640, 168, ['아란','브리테리아','웨스']],
[74, '브리테리아', '대', 7000,100,100, 80,100,100, '리자스 북부', 587, 205, ['아란','웨스','포나라']],
[75, '파란치', '소', 4500, 60, 60, 40, 60, 60, '리자스 북부', 667, 229, ['웨스','이스']],
[76, '노스', '중', 5500, 80, 80, 60, 80, 80, '리자스 남부', 563, 255, ['스케일','마우네스','오크','리자스성']],
[77, '오크', '중', 5500, 80, 80, 60, 80, 80, '리자스 남부', 577, 295, ['노스','사우스','지오']],
[78, '리자스성', '특', 8000,120,120,100,120,120, '리자스 남부', 611, 245, ['노스','사우스','웨스']],
[79, '사우스', '소', 4500, 60, 60, 40, 60, 60, '리자스 남부', 618, 285, ['리자스성','오크','이스']],
[80, '이스', '중', 5500, 80, 80, 60, 80, 80, '리자스 남부', 656, 269, ['사우스','파란치','오크스']],
[81, '오크스', '중', 5500, 80, 80, 60, 80, 80, '리자스 남부', 650, 311, ['이스','한나','오슈']],
[82, '웨스', '중', 5500, 80, 80, 60, 80, 80, '리자스 북부', 632, 212, ['리자스성','포나라','파란치','브리테리아']],
[83, '오슈', '이', 3500, 40, 40, 20, 40, 40, 'JAPAN', 688, 308, ['오크스','오와리']],
[84, '오와리', '특', 8000,120,120,100,120,120, 'JAPAN', 679, 394, ['오슈','모로코']],
[85, '모로코', '수', 2500, 20, 20, 20, 40, 40, 'JAPAN', 627, 450, ['오와리','포르투갈']],
[86, '지오', '중', 5500, 80, 80, 60, 80, 80, '자유도시 동부', 578, 333, ['오크','렛드','M랜드']],
[87, '한나', '소', 4500, 60, 60, 40, 60, 60, '자유도시 동부', 632, 342, ['오크스','M랜드']],
[88, 'M랜드', '대', 7000,100,100, 80,100,100, '자유도시 동부', 616, 379, ['지오','한나','렛드','포르투갈']],
[89, '포르투갈', '중', 5500, 80, 80, 60, 80, 80, '자유도시 동부', 599, 422, ['M랜드','투신도시','모로코']],
[90, '투신도시', '이', 3500, 40, 40, 20, 40, 40, '자유도시 동부', 553, 415, ['포르투갈','커스텀','파란쵸 왕국']],
[91, '화성', '소', 4500, 60, 60, 40, 60, 60, '자유도시 서부', 503, 482, ['커스텀']],
[92, '커스텀', '특', 8000,120,120,100,120,120, '자유도시 서부', 506, 416, ['투신도시','지브테리아','라지르','파란쵸 왕국','화성']],
[93, '라지르', '소', 4500, 60, 60, 40, 60, 60, '자유도시 서부', 530, 358, ['렛드','커스텀','아이스']],
[94, '록아스', '중', 5500, 80, 80, 60, 80, 80, '자유도시 서부', 489, 329, ['아이스','푸아']],
[95, '지브테리아', '대', 7000,100,100, 80,100,100, '자유도시 서부', 452, 370, ['아이스','카이즈','커스텀']],
[96, '파란쵸 왕국', '이', 3500, 40, 40, 20, 40, 40, '자유도시 동부', 537, 458, ['커스텀','투신도시']],
[97, '아이스', '소', 4500, 60, 60, 40, 60, 60, '자유도시 서부', 489, 375, ['록아스','지브테리아','라지르']],
[98, '렛드', '중', 5500, 80, 80, 60, 80, 80, '자유도시 서부', 566, 372, ['라지르','M랜드','지오']],
[99, '카이즈', '이', 3500, 40, 40, 20, 40, 40, 'AL교', 439, 425, ['올드제스','지브테리아']],
];
}

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