import tag_header,struct

class monster_attack_sequence:
	def __init__(self,dFile):
		self.flags=struct.unpack(">H", dFile.read(2))[0]
		self.sequence_index=struct.unpack(">h", dFile.read(2))[0]
		self.skip_fraction=struct.unpack(">H", dFile.read(2))[0]
		self.unused=struct.unpack(">h", dFile.read(2))[0]
		
class monster_attack_definition:
	def __init__(self,dFile):
		self.flags=struct.unpack(">H", dFile.read(2))[0]
		self.miss_fraction=struct.unpack(">H", dFile.read(2))[0]
		self.projectile_tag=struct.unpack(">L", dFile.read(4))[0]
		self.minimum_range=struct.unpack(">h", dFile.read(2))[0]
		self.maximum_range=struct.unpack(">h", dFile.read(2))[0]
		self.monsAttackSequences=[]
		for i in range(4):
			aMonsAttSeq=monster_attack_sequence(dFile)
			self.monsAttackSequences.append(aMonsAttSeq)
		self.repititions=struct.unpack(">h", dFile.read(2))[0]
		self.initial_velocity_lower_bound=struct.unpack(">h", dFile.read(2))[0]
		self.initial_velocity_delta=struct.unpack(">h", dFile.read(2))[0]
		self.initial_velocity_error=struct.unpack(">h", dFile.read(2))[0]
		self.recovery_time=struct.unpack(">h", dFile.read(2))[0]
		self.recovery_time_experience_delta=struct.unpack(">h", dFile.read(2))[0]
		self.velocity_improvement_with_experience=struct.unpack(">h", dFile.read(2))[0]
		self.mana_cost=struct.unpack(">h", dFile.read(2))[0]
		self.extra_flags=struct.unpack(">H", dFile.read(2))[0]
		self.projectile_type=struct.unpack(">h", dFile.read(2))[0]
	
class MONS:
	def __init__(self,dFile,dOffset,localFile, filePath):
		self.fPath=filePath
		MAXIMUM_NUMBER_OF_MONSTER_DEFINITION_SEQUENCES=32
		MAXIMUM_NUMBER_OF_TERRAIN_TYPES=16
		MAXIMUM_NUMBER_OF_ATTACKS_PER_MONSTER=4
		MAXIMUM_NUMBER_OF_MONSTER_DEFINITION_SOUNDS= 10
		self.tagHeader=tag_header.Tag_Header(dFile,dOffset)
		self.uID=-1
		if localFile>0:
			self.isLocal=True
		else:
			self.isLocal=False
			dFile.seek(self.tagHeader.getOffset())
		self.flags=struct.unpack(">L", dFile.read(4))[0]
		self.collection_tag=struct.unpack(">L", dFile.read(4))[0]
		self.sequence_indexes=[]
		for i in range(MAXIMUM_NUMBER_OF_MONSTER_DEFINITION_SEQUENCES):
			self.sequence_indexes.append(struct.unpack(">h", dFile.read(2))[0])
		self.terrain_costs=[]
		for i in range(MAXIMUM_NUMBER_OF_TERRAIN_TYPES):
			self.terrain_costs.append(struct.unpack(">c", dFile.read(1))[0])
		self.terrain_impassability_flags=struct.unpack(">H", dFile.read(2))[0]
		self.pathfinding_radius=struct.unpack(">h", dFile.read(2))[0]
		self.movement_modifiers=[]
		for i in range(MAXIMUM_NUMBER_OF_TERRAIN_TYPES):
			self.movement_modifiers.append(struct.unpack(">B", dFile.read(1))[0])
		self.absorbed_fraction=struct.unpack(">H", dFile.read(2))[0]
		self.warning_distance=struct.unpack(">h", dFile.read(2))[0]
		self.critical_distance=struct.unpack(">h", dFile.read(2))[0]
		self.healing_fraction=struct.unpack(">h", dFile.read(2))[0]
		self.initial_ammunition_lower_bound=struct.unpack(">h", dFile.read(2))[0]
		self.initial_ammunition_delta=struct.unpack(">h", dFile.read(2))[0]
		self.activation_distance=struct.unpack(">h", dFile.read(2))[0]
		self.unused=struct.unpack(">h", dFile.read(2))[0]
		self.turning_speed=struct.unpack(">H", dFile.read(2))[0]
		self.base_movement_speed=struct.unpack(">h", dFile.read(2))[0]
		self.left_handed_fraction=struct.unpack(">H", dFile.read(2))[0]
		self.size=struct.unpack(">h", dFile.read(2))[0]
		self.object_tag=struct.unpack(">L", dFile.read(4))[0]
		self.number_of_attacks=struct.unpack(">h", dFile.read(2))[0]
		self.desired_projectile_volume=struct.unpack(">h", dFile.read(2))[0]
		self.attacks=[]
		for i in range(MAXIMUM_NUMBER_OF_ATTACKS_PER_MONSTER):
			self.attacks.append(monster_attack_definition(dFile))
		self.map_action_tag=struct.unpack(">L", dFile.read(4))[0]
		self.attack_frequency_lower_bound=struct.unpack(">h", dFile.read(2))[0]
		self.attack_frequency_delta=struct.unpack(">h", dFile.read(2))[0]
		self.exploding_projectile_group_tag=struct.unpack(">L", dFile.read(4))[0]
		self.hack_flags=struct.unpack(">h", dFile.read(2))[0]
		self.maximum_ammunition_count=struct.unpack(">h", dFile.read(2))[0]
		self.hard_death_system_shock=struct.unpack(">H", dFile.read(2))[0]
		self.flinch_system_shock=struct.unpack(">H", dFile.read(2))[0]
		self.melee_impact_projectile_group_tag=struct.unpack(">L", dFile.read(4))[0]
		self.dying_projectile_group_tag=struct.unpack(">L", dFile.read(4))[0]
		self.spelling_string_list_tag=struct.unpack(">L", dFile.read(4))[0]
		self.names_string_list_tag=struct.unpack(">L", dFile.read(4))[0]
		self.flavor_string_list_tag=struct.unpack(">L", dFile.read(4))[0]
		self.use_attack_frequency=struct.unpack(">c", dFile.read(1))[0]
		self.unused3=struct.unpack(">c", dFile.read(1))[0] 
		self.monster_class=struct.unpack(">h", dFile.read(2))[0]
		self.monster_allegiance=struct.unpack(">h", dFile.read(2))[0]
		self.experience_point_value=struct.unpack(">h", dFile.read(2))[0]
		self.sound_tags=[]
		for i in range(MAXIMUM_NUMBER_OF_MONSTER_DEFINITION_SOUNDS):
			self.sound_tags.append(struct.unpack(">L", dFile.read(4))[0])
		self.blocked_impact_projectile_group_tag=struct.unpack(">L", dFile.read(4))[0]
		self.absorbed_impact_projectile_group_tag=struct.unpack(">L", dFile.read(4))[0]
		self.ammunition_projectile_tag=struct.unpack(">L", dFile.read(4))[0]
		self.visibility_type=struct.unpack(">h", dFile.read(2))[0]
		self.combined_power=struct.unpack(">h", dFile.read(2))[0]
		self.longest_range=struct.unpack(">h", dFile.read(2))[0]
		self.cost=struct.unpack(">h", dFile.read(2))[0]
		self.sound_types=[]
		for i in range(MAXIMUM_NUMBER_OF_MONSTER_DEFINITION_SOUNDS):
			self.sound_types.append(struct.unpack(">c", dFile.read(1))[0])
		self.enemy_experience_kill_bonus=struct.unpack(">h", dFile.read(2))[0]
		self.entrance_projectile_group_tag=struct.unpack(">L", dFile.read(4))[0]
		self.local_projectile_group_tag=struct.unpack(">L", dFile.read(4))[0]
		self.special_ability_string_list_tag=struct.unpack(">L", dFile.read(4))[0]
		self.exit_projectile_group_tag=struct.unpack(">L", dFile.read(4))[0]
		self.maximum_mana=struct.unpack(">h", dFile.read(2))[0]
		self.mana_recharge_rate=struct.unpack(">h", dFile.read(2))[0]
		self.berserk_system_shock=struct.unpack(">H", dFile.read(2))[0]
		self.berserk_vitality=struct.unpack(">H", dFile.read(2))[0]
		self.maximum_artifacts_carried=struct.unpack(">h", dFile.read(2))[0]
		self.unused2=dFile.read(430)
		# 	// computed during postprocessing
		self.next_name_string_index=struct.unpack(">h", dFile.read(2))[0]
		self.ammunition_projectile_type=struct.unpack(">h", dFile.read(2))[0]
		self.sound_indexes=[]
		for i in range(MAXIMUM_NUMBER_OF_MONSTER_DEFINITION_SOUNDS):
			self.sound_indexes.append(struct.unpack(">h", dFile.read(2))[0])
		self.spelling_string_list_index=struct.unpack(">h", dFile.read(2))[0]
		self.names_string_list_index=struct.unpack(">h", dFile.read(2))[0]
		self.flavor_string_list_index=struct.unpack(">h", dFile.read(2))[0]
		self.special_ability_string_list_index=struct.unpack(">h", dFile.read(2))[0]
		self.exploding_projectile_group_type=struct.unpack(">h", dFile.read(2))[0]
		self.melee_impact_projectile_group_type=struct.unpack(">h", dFile.read(2))[0]
		self.dying_projectile_group_type=struct.unpack(">h", dFile.read(2))[0]
		self.blocked_impact_projectile_group_type=struct.unpack(">h", dFile.read(2))[0]
		self.absorbed_impact_projectile_group_type=struct.unpack(">h", dFile.read(2))[0]
		self.entrance_projectile_group_type=struct.unpack(">h", dFile.read(2))[0]
		self.exit_projectile_group_type=struct.unpack(">h", dFile.read(2))[0]
		self.local_projectile_group_type=struct.unpack(">h", dFile.read(2))[0]
		self.collection_index=struct.unpack(">h", dFile.read(2))[0]
		self.object_type=struct.unpack(">h", dFile.read(2))[0]
		
	def getmName(self): return self.tagHeader.getName()
	def getmCode(self): return self.tagHeader.getSubgroup_Tag()
	def getuID(self): return self.uID
	def getIsLocal(self): return self.isLocal
	def setuID(self, theID):  self.uID=theID
	def getLinkedTags(self):
		tmpList=[]
		if tag_header.tagCheck(self.collection_tag) != "None":
			tmpList.append((self.collection_tag, '.256'))
		if tag_header.tagCheck(self.object_tag) != "None":
			tmpList.append((self.object_tag, 'obje'))
		if tag_header.tagCheck(self.exploding_projectile_group_tag) != "None":
			tmpList.append((self.exploding_projectile_group_tag, 'prgr'))
		if tag_header.tagCheck(self.melee_impact_projectile_group_tag) != "None":
			tmpList.append((self.melee_impact_projectile_group_tag, 'prgr'))
		if tag_header.tagCheck(self.dying_projectile_group_tag) != "None":
			tmpList.append((self.dying_projectile_group_tag, 'prgr'))
		if tag_header.tagCheck(self.spelling_string_list_tag) != "None":
			tmpList.append((self.spelling_string_list_tag, 'stli'))
		if tag_header.tagCheck(self.names_string_list_tag) != "None":
			tmpList.append((self.names_string_list_tag, 'stli'))
		if tag_header.tagCheck(self.flavor_string_list_tag) != "None":
			tmpList.append((self.flavor_string_list_tag, 'stli'))
		for dSound in self.sound_tags:
			if tag_header.tagCheck(dSound) != "None":
				tmpList.append((dSound, 'soun'))
		if tag_header.tagCheck(self.blocked_impact_projectile_group_tag) != "None":
			tmpList.append((self.blocked_impact_projectile_group_tag, 'prgr'))
		if tag_header.tagCheck(self.absorbed_impact_projectile_group_tag) != "None":
			tmpList.append((self.absorbed_impact_projectile_group_tag, 'prgr'))
		if tag_header.tagCheck(self.ammunition_projectile_tag) != "None":
			tmpList.append((self.ammunition_projectile_tag, 'proj'))
		if tag_header.tagCheck(self.entrance_projectile_group_tag) != "None":
			tmpList.append((self.entrance_projectile_group_tag, 'prgr'))
		if tag_header.tagCheck(self.local_projectile_group_tag) != "None":
			tmpList.append((self.local_projectile_group_tag, 'prgr'))
		if tag_header.tagCheck(self.special_ability_string_list_tag) != "None":
			tmpList.append((self.special_ability_string_list_tag, 'stli'))
		if tag_header.tagCheck(self.exit_projectile_group_tag) != "None":
			tmpList.append((self.exit_projectile_group_tag, 'prgr'))
		for dAttack in self.attacks:
			if tag_header.tagCheck(dAttack.projectile_tag) != "None":
				tmpList.append((dAttack.projectile_tag, 'proj'))
		if len(tmpList)>0:
			return tmpList
		else:
			return False
		
		
		
		
		
		
		