[Enhance][Bug fix] Fatalis values & Salt skill
Merged from commit a23e5372fb8d8dcff193a72a6d8fc778c28ef177 - Revised Salt's skill implemtation (used Lost's implementation) - Add support for dynamic values of "Hikari (Fatalis)", which is depended by world mode total steps. - Fix a bug that the character "Hikari (Fatalis)" cannot be used in world mode.(due to 3f5281582cc2e9141e748a99fadb385db522e664) - Another attempt at fixing Nell's world map traversal
This commit is contained in:
parent
c4659ed8cd
commit
488b8625da
8 changed files with 106 additions and 16 deletions
|
@ -2,6 +2,7 @@ from .config_manager import Config
|
|||
from .constant import Constant
|
||||
from .error import ArcError, InputError, ItemNotEnough, NoData
|
||||
from .item import CollectionItemMixin, ItemCore
|
||||
from .sql import UserKVTable
|
||||
|
||||
|
||||
class Level:
|
||||
|
@ -55,6 +56,7 @@ class Skill:
|
|||
class CharacterValue:
|
||||
def __init__(self, start: float = 0, mid: float = 0, end: float = 0) -> None:
|
||||
self.set_parameter(start, mid, end)
|
||||
self.addition: float = 0
|
||||
|
||||
@staticmethod
|
||||
def _calc_char_value_20_math(level: int, value_1: float, value_20: float) -> float:
|
||||
|
@ -87,9 +89,9 @@ class CharacterValue:
|
|||
|
||||
def get_value(self, level: Level):
|
||||
if level.min_level <= level.level <= level.mid_level:
|
||||
return self._calc_char_value_20_math(level.level, self.start, self.mid)
|
||||
return self._calc_char_value_20_math(level.level, self.start, self.mid) + self.addition
|
||||
if level.mid_level < level.level <= level.max_level:
|
||||
return self._calc_char_value_30(level.level, self.mid, self.end)
|
||||
return self._calc_char_value_30(level.level, self.mid, self.end) + self.addition
|
||||
return 0
|
||||
|
||||
|
||||
|
@ -231,6 +233,8 @@ class UserCharacter(Character):
|
|||
|
||||
self.skill_flag: bool = None
|
||||
|
||||
self.fatalis_is_limited: bool = False
|
||||
|
||||
@property
|
||||
def skill_id_displayed(self) -> str:
|
||||
'''对外显示的技能id'''
|
||||
|
@ -295,6 +299,22 @@ class UserCharacter(Character):
|
|||
if self.character_id in (21, 46):
|
||||
self.voice = [0, 1, 2, 3, 100, 1000, 1001]
|
||||
|
||||
if self.character_id == 55:
|
||||
# fatalis 提升数值
|
||||
# prog & overdrive += 世界模式中完成的所有非无限地图的台阶数之和 / 30
|
||||
if Config.CHARACTER_FULL_UNLOCK:
|
||||
addition = Constant.FATALIS_MAX_VALUE
|
||||
self.fatalis_is_limited = True
|
||||
else:
|
||||
kvd = UserKVTable(self.c, self.user.user_id, 'world')
|
||||
steps = kvd['total_step_count'] or 0
|
||||
addition = steps / 30
|
||||
if addition >= Constant.FATALIS_MAX_VALUE:
|
||||
addition = Constant.FATALIS_MAX_VALUE
|
||||
self.fatalis_is_limited = True
|
||||
self.prog.addition = addition
|
||||
self.overdrive.addition = addition
|
||||
|
||||
self.select_character_core()
|
||||
if self.character_id == 72:
|
||||
self.update_insight_state()
|
||||
|
@ -323,7 +343,7 @@ class UserCharacter(Character):
|
|||
if self.voice:
|
||||
r['voice'] = self.voice
|
||||
if self.character_id == 55:
|
||||
r['fatalis_is_limited'] = False # emmmmmmm
|
||||
r['fatalis_is_limited'] = self.fatalis_is_limited
|
||||
if self.character_id in [1, 6, 7, 17, 18, 24, 32, 35, 52]:
|
||||
r['base_character_id'] = 1
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from .config_manager import Config
|
||||
|
||||
ARCAEA_SERVER_VERSION = 'v2.12.0.3'
|
||||
ARCAEA_SERVER_VERSION = 'v2.12.0.4'
|
||||
ARCAEA_DATABASE_VERSION = 'v2.12.0.4'
|
||||
ARCAEA_LOG_DATBASE_VERSION = 'v1.1'
|
||||
|
||||
|
@ -32,6 +32,7 @@ class Constant:
|
|||
SKILL_FATALIS_WORLD_LOCKED_TIME = 3600000
|
||||
SKILL_MIKA_SONGS = ['aprilshowers', 'seventhsense', 'oshamascramble', 'breakbreak', 'straightintolights', 'virtus', 'yomibitoshirazu',
|
||||
'amazingmightyyyy', 'cycles', 'maxrage', 'infinity', 'temptation']
|
||||
FATALIS_MAX_VALUE = 100
|
||||
|
||||
MAX_FRIEND_COUNT = Config.MAX_FRIEND_COUNT
|
||||
|
||||
|
@ -68,7 +69,6 @@ class Constant:
|
|||
LINKPLAY_TCP_SECRET_KEY = Config.LINKPLAY_TCP_SECRET_KEY
|
||||
LINKPLAY_TCP_MAX_LENGTH = 0x0FFFFFFF
|
||||
|
||||
|
||||
LINKPLAY_MATCH_GET_ROOMS_INTERVAL = 4 # Units: seconds
|
||||
LINKPLAY_MATCH_PTT_ABS = [5, 20, 50, 100, 200, 500, 1000, 2000]
|
||||
LINKPLAY_MATCH_UNLOCK_MIN = [1000, 800, 500, 300, 200, 100, 50, 1]
|
||||
|
|
|
@ -377,6 +377,7 @@ class UserPlay(UserScore):
|
|||
if self.user.stamina.stamina < self.user.current_map.stamina_cost * self.stamina_multiply:
|
||||
raise StaminaNotEnough('Stamina is not enough.')
|
||||
|
||||
fatalis_stamina_multiply = 1
|
||||
self.user.select_user_about_character()
|
||||
if not self.user.is_skill_sealed:
|
||||
self.user.character.select_character_info()
|
||||
|
@ -387,16 +388,13 @@ class UserPlay(UserScore):
|
|||
self.invasion_flag = _flag
|
||||
elif self.user.character.skill_id_displayed == 'skill_fatalis':
|
||||
# 特殊判断hikari fatalis的双倍体力消耗
|
||||
self.user.stamina.stamina -= self.user.current_map.stamina_cost * \
|
||||
self.stamina_multiply * 2
|
||||
self.user.stamina.update()
|
||||
return None
|
||||
fatalis_stamina_multiply = 2
|
||||
|
||||
self.clear_play_state()
|
||||
self.c.execute('''insert into songplay_token values(:t,:a,:b,:c,'',-1,0,0,:d,:e,:f,:g,:h,:i,:j)''', {
|
||||
'a': self.user.user_id, 'b': self.song.song_id, 'c': self.song.difficulty, 'd': self.stamina_multiply, 'e': self.fragment_multiply, 'f': self.prog_boost_multiply, 'g': self.beyond_boost_gauge_usage, 'h': self.skill_cytusii_flag, 'i': self.skill_chinatsu_flag, 'j': self.invasion_flag, 't': self.song_token})
|
||||
|
||||
self.user.stamina.stamina -= self.user.current_map.stamina_cost * self.stamina_multiply
|
||||
self.user.stamina.stamina -= self.user.current_map.stamina_cost * self.stamina_multiply * fatalis_stamina_multiply
|
||||
self.user.stamina.update()
|
||||
|
||||
def set_play_state_for_course(self, use_course_skip_purchase: bool, course_id: str = None) -> None:
|
||||
|
|
32
core/sql.py
32
core/sql.py
|
@ -525,3 +525,35 @@ class MemoryDatabase:
|
|||
@register
|
||||
def atexit():
|
||||
MemoryDatabase.conn.close()
|
||||
|
||||
|
||||
class UserKVTable:
|
||||
'''用户键值对表'''
|
||||
|
||||
def __init__(self, c=None, user_id: int = None, class_name: str = None) -> None:
|
||||
self.c = c
|
||||
self.user_id = user_id
|
||||
self.class_name = class_name
|
||||
|
||||
def get(self, key: str, idx: int = 0):
|
||||
'''获取键值对'''
|
||||
x = self.c.execute(
|
||||
'''select value from user_kvdata where user_id = ? and class = ? and key = ? and idx = ?''', (self.user_id, self.class_name, key, idx)).fetchone()
|
||||
return x[0] if x else None
|
||||
|
||||
def set(self, key: str, value, idx: int = 0) -> None:
|
||||
'''设置键值对'''
|
||||
self.c.execute('''insert or replace into user_kvdata values(?,?,?,?,?)''',
|
||||
(self.user_id, self.class_name, key, idx, value))
|
||||
|
||||
def __getitem__(self, args):
|
||||
if isinstance(args, tuple):
|
||||
return self.get(*args)
|
||||
else:
|
||||
return self.get(args)
|
||||
|
||||
def __setitem__(self, args, value):
|
||||
if isinstance(args, tuple):
|
||||
self.set(args[0], value, args[1])
|
||||
else:
|
||||
self.set(args, value)
|
||||
|
|
33
core/user.py
33
core/user.py
|
@ -13,8 +13,8 @@ from .item import UserItemList
|
|||
from .limiter import ArcLimiter
|
||||
from .mission import UserMissionList
|
||||
from .score import Score
|
||||
from .sql import Query, Sql
|
||||
from .world import Map, UserMap, UserStamina
|
||||
from .sql import Query, Sql, UserKVTable
|
||||
from .world import Map, MapParser, UserMap, UserStamina
|
||||
|
||||
|
||||
def code_get_id(c, user_code: str) -> int:
|
||||
|
@ -741,6 +741,35 @@ class UserInfo(User):
|
|||
'''update user set world_rank_score = ? where user_id = ?''', (x[0], self.user_id))
|
||||
self.world_rank_score = x[0]
|
||||
|
||||
def update_user_world_complete_info(self) -> None:
|
||||
'''
|
||||
更新用户的世界模式完成信息,包括两个部分
|
||||
|
||||
1. 每个章节的完成地图数量,为了 salt 技能
|
||||
2. 全世界模式完成台阶数之和,为了 fatalis 技能
|
||||
'''
|
||||
kvd = UserKVTable(self.c, self.user_id, 'world')
|
||||
|
||||
for chapter_id, map_ids in MapParser.chapter_info_without_repeatable.items():
|
||||
self.c.execute(
|
||||
f'''select map_id, curr_position from user_world where user_id = ? and map_id in ({','.join(['?']*len(map_ids))})''',
|
||||
(self.user_id, *map_ids)
|
||||
)
|
||||
x = self.c.fetchall()
|
||||
n = 0
|
||||
for map_id, curr_position in x:
|
||||
step_count = MapParser.world_info[map_id]['step_count']
|
||||
if curr_position == step_count - 1:
|
||||
n += 1
|
||||
kvd['chapter_complete_count', chapter_id] = n
|
||||
|
||||
self.c.execute(
|
||||
'''select sum(curr_position) + count(*) from user_world where user_id = ?''', (self.user_id,)
|
||||
)
|
||||
x = self.c.fetchone()
|
||||
if x is not None:
|
||||
kvd['total_step_count'] = x[0] or 0
|
||||
|
||||
def select_user_one_column(self, column_name: str, default_value=None, data_type=None) -> None:
|
||||
'''
|
||||
查询user表的某个属性
|
||||
|
|
|
@ -30,13 +30,13 @@ class InitData:
|
|||
46, 73, 95, 67, 84, 70, 78, 69, 70, 50, 80, 80, 63, 25, 50, 72, 55, 50, 95, 55, 70, 90, 70, 99, 80, 61, 40, 69, 62, 51, 90, 67, 60, 100, 200, 85, 50, 92, 50, 75, 80, 49.5, 50, 100, 51, 54, 65.5, 59.5, 58, 96, 47, 75, 54, 90, 41, 34, 30, 55, 66, 55, 62, 81, 44, 46]
|
||||
|
||||
frag30 = [88, 90, 100, 75, 80, 89, 70, 79, 65, 40, 50, 90, 100, 92, 0, 61, 67, 92, 85, 50, 86, 62,
|
||||
65, 95, 67, 88, 74, 0.5, 105, 80, 105, 50, 80, 87, 81, 50, 95, 0, 80, 75, 50, 70, 80, 100, 65, 80, 61, 50, 68, 60, 90, 67, 50, 60, 51, 50, 35, 85, 47, 50, 75, 80, 90, 80, 50, 51, 64, 100, 50, 58, 51, 40, 115, 80, 50, 61.6, 48, 37, 90, 60, 50, 102, 76, 0, 89]
|
||||
65, 95, 67, 88, 74, 0.5, 105, 80, 105, 50, 80, 87, 81, 50, 95, 0, 80, 75, 50, 70, 80, 100, 65, 80, 61, 50, 68, 60, 90, 67, 50, 60, 51, 50, 35, 85, 47, 50, 75, 80, 90, 80, 50, 51, 64, 100, 50, 58, 51, 40, 115, 80, 50, 61.6, 48, 37, 90, 60, 50, 102, 76, 44, 89]
|
||||
|
||||
prog30 = [71, 90, 80, 75, 100, 80, 90, 102, 84, 78, 110, 77, 73, 78, 0, 99, 80, 66, 46, 93, 40, 83,
|
||||
80, 100, 93, 50, 96, 88, 99, 108, 85, 80, 50, 64, 65, 100, 100, 110, 80, 50, 74, 90, 80, 80, 56, 80, 79, 55, 65, 59, 90, 50, 90, 90, 75, 210, 35, 86, 92, 80, 75, 100, 60, 50, 68, 51, 60, 53, 85, 58, 96, 47, 80, 90, 67, 41, 55, 50, 103, 66, 35, 62, 75, 0, 53]
|
||||
80, 100, 93, 50, 96, 88, 99, 108, 85, 80, 50, 64, 65, 100, 100, 110, 80, 50, 74, 90, 80, 80, 56, 80, 79, 55, 65, 59, 90, 50, 90, 90, 75, 210, 35, 86, 92, 80, 75, 100, 60, 50, 68, 51, 60, 53, 85, 58, 96, 47, 80, 90, 67, 41, 55, 50, 103, 66, 35, 62, 75, 50, 53]
|
||||
|
||||
overdrive30 = [71, 90, 57, 75, 80, 80, 95, 79, 65, 31, 50, 69, 100, 68, 0, 78, 50, 70, 62, 59, 64,
|
||||
56, 73, 105, 67, 84, 80, 88, 79, 80, 60, 80, 80, 63, 35, 50, 82, 55, 50, 95, 55, 70, 100, 80, 99, 80, 61, 40, 69, 62, 51, 90, 67, 60, 100, 200, 85, 50, 92, 50, 75, 80, 49.5, 50, 100, 51, 64, 65.5, 59.5, 58, 96, 47, 75, 64, 90, 41, 34, 30, 55, 66, 55, 72, 91, 0, 56]
|
||||
56, 73, 105, 67, 84, 80, 88, 79, 80, 60, 80, 80, 63, 35, 50, 82, 55, 50, 95, 55, 70, 100, 80, 99, 80, 61, 40, 69, 62, 51, 90, 67, 60, 100, 200, 85, 50, 92, 50, 75, 80, 49.5, 50, 100, 51, 64, 65.5, 59.5, 58, 96, 47, 75, 64, 90, 41, 34, 30, 55, 66, 55, 72, 91, 44, 56]
|
||||
|
||||
char_type = [1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 2, 0, 0, 0, 2, 3, 1, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 2, 2, 0, 0, 2, 0, 0, 2, 0, 2, 2, 1, 0, 2, 0, 4, 2, 0, 0, 0, 0, 4, 0, 0, 0, 2, 0, 2]
|
||||
|
|
|
@ -283,6 +283,17 @@ status int,
|
|||
primary key(user_id, mission_id)
|
||||
);
|
||||
|
||||
-- value 无类型
|
||||
create table if not exists user_kvdata(
|
||||
user_id int,
|
||||
class text,
|
||||
key text,
|
||||
idx int,
|
||||
value,
|
||||
primary key(user_id, class, key, idx)
|
||||
);
|
||||
|
||||
|
||||
create index if not exists best_score_1 on best_score (song_id, difficulty);
|
||||
|
||||
PRAGMA journal_mode = WAL;
|
||||
|
|
|
@ -443,7 +443,7 @@ def all_character():
|
|||
def change_character():
|
||||
# 修改角色数据
|
||||
skill_ids = ['No_skill', 'gauge_easy', 'note_mirror', 'gauge_hard', 'frag_plus_10_pack_stellights', 'gauge_easy|frag_plus_15_pst&prs', 'gauge_hard|fail_frag_minus_100', 'frag_plus_5_side_light', 'visual_hide_hp', 'frag_plus_5_side_conflict', 'challenge_fullcombo_0gauge', 'gauge_overflow', 'gauge_easy|note_mirror', 'note_mirror', 'visual_tomato_pack_tonesphere',
|
||||
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', 'frags_kou', 'visual_ink', 'shirabe_entry_fee', 'frags_yume', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion', 'skill_lagrange', 'gauge_safe_10', 'frags_nami', 'skill_elizabeth', 'skill_lily', 'skill_kanae_midsummer', 'eto_uncap', 'luna_uncap', 'frags_preferred_song', 'visual_ghost_skynotes', 'ayu_uncap', 'skill_vita', 'skill_fatalis', 'skill_reunion', 'frags_ongeki_slash', 'frags_ongeki_hard', 'skill_amane', 'skill_kou_winter', 'gauge_hard|note_mirror', 'skill_shama', 'skill_milk', 'skill_shikoku', 'skill_mika', 'ilith_awakened_skill', 'skill_mithra', 'skill_toa', 'skill_nami_twilight', 'skill_ilith_ivy', 'skill_hikari_vanessa', 'skill_maya', 'skill_luin', 'skill_luin_uncap', 'skill_kanae_uncap', 'skill_doroc_uncap', 'skill_saya_uncap', 'skill_luna_ilot', 'skill_eto_hoppe', 'skill_aichan', 'skill_nell', 'skill_chinatsu', 'skill_tsumugi', 'skill_nai', 'skill_selene']
|
||||
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', 'frags_kou', 'visual_ink', 'shirabe_entry_fee', 'frags_yume', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion', 'skill_lagrange', 'gauge_safe_10', 'frags_nami', 'skill_elizabeth', 'skill_lily', 'skill_kanae_midsummer', 'eto_uncap', 'luna_uncap', 'frags_preferred_song', 'visual_ghost_skynotes', 'ayu_uncap', 'skill_vita', 'skill_fatalis', 'skill_reunion', 'frags_ongeki_slash', 'frags_ongeki_hard', 'skill_amane', 'skill_kou_winter', 'gauge_hard|note_mirror', 'skill_shama', 'skill_milk', 'skill_shikoku', 'skill_mika', 'ilith_awakened_skill', 'skill_mithra', 'skill_toa', 'skill_nami_twilight', 'skill_ilith_ivy', 'skill_hikari_vanessa', 'skill_maya', 'skill_luin', 'skill_luin_uncap', 'skill_kanae_uncap', 'skill_doroc_uncap', 'skill_saya_uncap', 'skill_luna_ilot', 'skill_eto_hoppe', 'skill_aichan', 'skill_nell', 'skill_chinatsu', 'skill_tsumugi', 'skill_nai', 'skill_selene', 'skill_salt', 'skill_acid']
|
||||
return render_template('web/changechar.html', skill_ids=skill_ids)
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue