// proj.h
#ifndef __proj_h__
#define __proj_h__

#ifndef __tags_h__
#include "tags.h"
#endif

#ifndef __BYTE_SWAPPING_H__
#include "byte_swapping.h"
#endif

#ifndef __ttageditform_h__
#include "TTagEditForm.h"
#endif

#ifndef __myth_defs_h__
#include "myth_defs.h"
#endif

#ifndef __damage_h__
#include "damage.h"
#endif


/* ---------- constants */

enum
{
	PROJECTILE_DEFINITION_GROUP_TAG= 0x70726f6a, // 'proj' (looks like text)
	PROJECTILE_DEFINITION_VERSION_NUMBER= 1,

	MAXIMUM_PROJECTILE_DEFINITIONS_PER_MAP= 172
};

/* ---------- definition */

enum // constants
{
	MAXIMUM_PROJECTILE_PERMUTATIONS= 6
};

enum // .splash_or_rebound_effect_type (can be NONE)
{
	_small_splash_or_rebound, // rocks, arrows
	_medium_splash_or_rebound, // body parts
	_large_splash_or_rebound, // torsos
	NUMBER_OF_SPLASH_OR_REBOUND_EFFECT_TYPES
};

enum // .volume
{
	_volume_unwieldy, // stuff that can't be picked up readily
	_volume_small, // heads, arms, legs, axe heads, sword hilts, small rocks, etc.
	_volume_large, // torsos, big rocks, tathlum, demon heads, etc.
	
	NUMBER_OF_PROJECTILE_VOLUMES
};

enum // sounds
{
	_projectile_sound_flight, // played when the projectile is created
	_projectile_sound_rebound,
	NUMBER_OF_PROJECTILE_DEFINITION_SOUNDS, // <=MAXIMUM_NUMBER_OF_PROJECTILE_DEFINITION_SOUNDS
	
	MAXIMUM_NUMBER_OF_PROJECTILE_DEFINITION_SOUNDS= 4
};

enum // projectile class
{
	_projectile_class_unknown,
	_projectile_class_head,
	_projectile_class_arm,
	_projectile_class_leg,
	_projectile_class_torso,
	_projectile_class_bloody_chunk, // any piece of flesh that doesn't fall into the above categories
	_projectile_class_lethal_object, // any loose piece of equipment or scenery which can cause damage
	_projectile_class_nonlethal_object, // any loose piece of equipment or scenery which cannot cause damage
	_projectile_class_explosive_object, // object can explode on contact
	_projectile_class_potentially_explosive_object, // object can explode when exposed to fire
	_projectile_class_item // projectile is a usable item of some sort
};

enum // sequences
{
	_projectile_sequence_in_flight,
	_projectile_sequence_detonation_stain,
	_projectile_sequence_bounce_stain,
	NUMBER_OF_PROJECTILE_DEFINITION_SEQUENCES,
	
	MAXIMUM_NUMBER_OF_PROJECTILE_DEFINITION_SEQUENCES= 3
};

enum // animations.
{
	_projectile_anim_in_flight,
	_projectile_anim_detonation_stain,
	_projectile_anim_bounce_stain,
	NUMBER_OF_PROJECTILE_DEFINITION_ANIMATIONS,
	
	MAXIMUM_NUMBER_OF_PROJECTILE_DEFINITION_ANIMATIONS= 3
};

enum // projectile definition flags
{
	_projectile_uses_owner_color_table_index_bit,
	_projectile_is_guided_bit,
	_projectile_is_bloody_do_not_draw_bit,
	_projectile_detonates_when_animation_loops_bit,

	_projectile_detonates_when_transfer_loops_bit,
	_projectile_detonates_at_rest_bit,
	_projectile_affected_by_wind_bit, // global wind direction added to initial velocity
	_projectile_animates_at_rest_bit, // implied by _projectile_detonates_when_animation_loops_bit or _projectile_detonates_when_transfer_loops_bit

	_projectile_becomes_dormant_at_rest_bit,
	_projectile_angle_follows_trajectory_bit,
	_projectile_contrail_frequency_reset_after_bouncing_bit,
	_projectile_can_be_mirrored_bit,

	_projectile_is_promoted_at_end_of_lifespan_bit,
	_projectile_is_melee_attack_bit, // no physical presence
	_projectile_cannot_be_accelerated_bit, // for smoke, etc.
	_projectile_bloodies_landscape_bit,

	_projectile_is_on_fire_bit, // put out (i.e., promoted) by thick atmospheric effects or water
	_projectile_remains_after_detonation_bit,
	_projectile_passes_through_target_bit,
	_projectile_cannot_be_mirrored_vertically_bit,

	_projectile_floats_bit,
	_projectile_is_media_surface_effect_bit,
	_projectile_uses_sprite_contrail_bit,
	_projectile_only_destroyed_by_lifespan_bit,

	_projectile_is_lightning_bit,
	_projectile_chooses_nearby_target_bit,
	_projectile_continually_detonates_bit,
	_projectile_makes_owner_monster_visible_bit,
	
	_projectile_can_set_landscape_on_fire_bit,
	_projectile_centered_on_target_bit,
	_projectile_marks_target_has_having_been_chosen_bit, // to take damage
	_projectile_definition_detonates_immediately_bit,
	
	NUMBER_OF_PROJECTILE_DEFINITION_FLAGS,
	
	_projectile_uses_owner_color_table_index_flag= FLAG(_projectile_uses_owner_color_table_index_bit),
	_projectile_is_guided_flag= FLAG(_projectile_is_guided_bit),
	_projectile_is_bloody_do_not_draw_flag= FLAG(_projectile_is_bloody_do_not_draw_bit),
	_projectile_detonates_when_animation_loops_flag= FLAG(_projectile_detonates_when_animation_loops_bit),
	_projectile_detonates_when_transfer_loops_flag= FLAG(_projectile_detonates_when_transfer_loops_bit),
	_projectile_detonates_at_rest_flag= FLAG(_projectile_detonates_at_rest_bit),
	_projectile_affected_by_wind_flag= FLAG(_projectile_affected_by_wind_bit),
	_projectile_animates_at_rest_flag= FLAG(_projectile_animates_at_rest_bit),
	_projectile_becomes_dormant_at_rest_flag= FLAG(_projectile_becomes_dormant_at_rest_bit),
	_projectile_angle_follows_trajectory_flag= FLAG(_projectile_angle_follows_trajectory_bit),
	_projectile_contrail_frequency_reset_after_bouncing_flag= FLAG(_projectile_contrail_frequency_reset_after_bouncing_bit),
	_projectile_can_be_mirrored_flag= FLAG(_projectile_can_be_mirrored_bit),
	_projectile_is_promoted_at_end_of_lifespan_flag= FLAG(_projectile_is_promoted_at_end_of_lifespan_bit),
	_projectile_is_melee_attack_flag= FLAG(_projectile_is_melee_attack_bit),
	_projectile_cannot_be_accelerated_flag= FLAG(_projectile_cannot_be_accelerated_bit),
	_projectile_bloodies_landscape_flag= FLAG(_projectile_bloodies_landscape_bit),
	_projectile_is_on_fire_flag= FLAG(_projectile_is_on_fire_bit),
	_projectile_remains_after_detonation_flag= FLAG(_projectile_remains_after_detonation_bit),
	_projectile_passes_through_target_flag= FLAG(_projectile_passes_through_target_bit),
	_projectile_cannot_be_mirrored_vertically_flag= FLAG(_projectile_cannot_be_mirrored_vertically_bit),
	_projectile_floats_flag= FLAG(_projectile_floats_bit),
	_projectile_is_media_surface_effect_flag= FLAG(_projectile_is_media_surface_effect_bit),
	_projectile_uses_sprite_contrail_flag= FLAG(_projectile_uses_sprite_contrail_bit),
	_projectile_only_destroyed_by_lifespan_flag= FLAG(_projectile_only_destroyed_by_lifespan_bit),
	_projectile_is_lightning_flag= FLAG(_projectile_is_lightning_bit),
	_projectile_chooses_nearby_target_flag= FLAG(_projectile_chooses_nearby_target_bit),
	_projectile_continually_detonates_flag= FLAG(_projectile_continually_detonates_bit),
	_projectile_makes_owner_monster_visible_flag= FLAG(_projectile_makes_owner_monster_visible_bit),
	_projectile_can_set_landscape_on_fire_flag= FLAG(_projectile_can_set_landscape_on_fire_bit),
	_projectile_centered_on_target_flag= FLAG(_projectile_centered_on_target_bit),
	_projectile_marks_target_has_having_been_chosen_flag= FLAG(_projectile_marks_target_has_having_been_chosen_bit),
	_projectile_definition_detonates_immediately_flag= FLAG(_projectile_definition_detonates_immediately_bit)
};

/* ---------- structures */

/*
the definition editor for projectiles should provide a high-level checkbox for "effect" which
sets and hides irrelevant options: speed, range, radius, area_of_effect, damage,
*/

#define SIZEOF_STRUCT_PROJECTILE_DEFINITION 256
struct projectile_definition
{
	unsigned long flags;
	
	union {
		file_tag collection_tag;
		file_tag skelmodel_tag;
	};
	
	short sequence_indexes[MAXIMUM_NUMBER_OF_PROJECTILE_DEFINITION_SEQUENCES];
	
	short splash_or_rebound_effect_type;
	file_tag detonation_projectile_group_tag;
	
	file_tag contrail_projectile_or_sprite_tag;
	short ticks_between_contrails, maximum_contrail_count;
	
	file_tag object_tag;

	short_fixed inertia_lower_bound, inertia_delta; // 1.0 is standard, 0.0 is infinite (how much acceleration we accept)
	short_world_distance random_initial_velocity; // applied in a random direction
	short volume;
	short tracking_priority;
	fixed_fraction promotion_on_detonation_fraction; // chance this projectile will be promoted instead of detonating
	
	fixed_fraction detonation_frequency, media_detonation_frequency;
	short_world_distance detonation_velocity; // can be zero (will take highest of local and external)
	
	short projectile_class;
	
	file_tag lightning_tag;
	
	short unused[2];
	file_tag sound_tags[MAXIMUM_NUMBER_OF_PROJECTILE_DEFINITION_SOUNDS];
	
	short_fixed animation_rate_lower_bound, animation_rate_delta;
	short lifespan_lower_bound, lifespan_delta; // in ticks, zero is maximum
	
	fixed_fraction initial_contrail_frequency, final_contrail_frequency;
	fixed_fraction contrail_frequency_delta;
	angle guided_turning_speed;
	
	file_tag promoted_projectile_tag; // the tag we become if we are promoted
	file_tag promotion_projectile_group_tag; // the projectile group created if we are promoted
	file_tag bounce_stain_texturestacks_tag;
	
	struct damage_definition damage;

	file_tag artifact_tag;
	file_tag target_detonation_projectile_group_tag;
	file_tag detonation_stain_texturestacks_tag;

	short delay_lower_bound, delay_delta;

	file_tag local_projectile_group_tag;
	
	short nearby_target_radius; // in cells; only valid if bit set
	word pad2;
	
	unsigned short skelmodel_code;
	byte blood_rgba[4];
	
	short unused3[35];
	
	// computed during postprocessing
	
	short bounce_stain_txst_index;
	short detonation_stain_txst_index;
	short local_projectile_group_type;
	short target_detonation_projectile_group_type;
	short lightning_index, artifact_index;
	short detonation_projectile_group_type, contrail_projectile_or_sprite_type;
	short promotion_projectile_group_type, promoted_projectile_type;

	short sound_indexes[MAXIMUM_NUMBER_OF_PROJECTILE_DEFINITION_SOUNDS];	
	short skelmodel_index, collection_index, color_table_index;
	short object_type;
};


//=====================================================================================================
bool read_projectile_definition( projectile_definition* def, tag id );
bool save_projectile_definition( projectile_definition* def, tag id );

bool read_projectile_definition( projectile_definition* def, tag_entry* e );
bool save_projectile_definition( projectile_definition* def, tag_entry* e );

class TprojEditForm: public TTagEditForm {
	public:
							TprojEditForm( struct tag_entry *e );
				
		DECLAREDISPATCH
		virtual long		DoControlClick( long arg, void *ptr );
		
		virtual void		CommitToTag();
		virtual void		ReloadTag();
		virtual bool		NeedCommit();
		virtual void		DoFormInitialize();
		
	protected:
		void				SetValues();
		void				GetValues();
		void				LoadAnimLists();
		projectile_definition	def;
};


#endif